pax_global_header00006660000000000000000000000064152025212050014504gustar00rootroot0000000000000052 comment=41e81189613ff3060fa5cc372e871f61cbcd78c2 stgit-2.6.0/000077500000000000000000000000001520252120500126435ustar00rootroot00000000000000stgit-2.6.0/.gitattributes000066400000000000000000000000521520252120500155330ustar00rootroot00000000000000* text=auto eol=lf .github/ export-ignore stgit-2.6.0/.gitignore000066400000000000000000000000751520252120500146350ustar00rootroot00000000000000/completion/stg.fish /completion/stgit.bash /htmlcov /target stgit-2.6.0/.mailmap000066400000000000000000000004171520252120500142660ustar00rootroot00000000000000# This list is used by various git commands to fix a few botched name # translations in the StGit repository. Bryan Larsen Bryan Larsen Karl Wiberg Paolo 'Blaisorblade' Giarrusso stgit-2.6.0/AUTHORS.md000066400000000000000000000057431520252120500143230ustar00rootroot00000000000000# Authors StGit was originally written by Catalin Marinas, and is currently maintained by Catalin Marinas and Peter Grayson. Thanks go out to StGit's many contributors: - Catalin Marinas ([@ctmarinas](https://github.com/ctmarinas)) - Peter Grayson ([@jpgrayson](https://github.com/jpgrayson)) - Karl Wiberg ([@kwiberg](https://github.com/kwiberg)) - Yann Dirson ([@ydirson](https://github.com/ydirson)) - Gustav Hållberg ([@Gustavigator](https://github.com/Gustavigator)) - David Kågedal ([@dkagedal](https://github.com/dkagedal)) - Chuck Lever ([@chucklever](https://github.com/chucklever)) - Pavel Roskin ([@proski](https://github.com/proski)) - Paolo Giarrusso ([@Blaisorblade](https://github.com/Blaisorblade)) - Daniel White ([@danielwhite](https://github.com/danielwhite)) - Zane Bitter ([@zaneb](https://github.com/zaneb)) - Alex Chiang - Jacob Keller - Vincent Legoll ([@vincele](https://github.com/vincele)) - Robin Rosenberg ([@robinrosenberg](https://github.com/robinrosenberg)) - Peter P Waskiewicz Jr - Bryan Larsen ([@bryanlarsen](https://github.com/bryanlarsen)) - Clark Williams ([@clrkwllms](https://github.com/clrkwllms)) - Dan Williams ([@djbw](https://github.com/djbw)) - Lu Guanqun ([@guanqun](https://github.com/guanqun)) - Onno Kortmann ([@onnokort](https://github.com/onnokort)) - Peter Oberndorfer ([@kumbayo](https://github.com/kumbayo)) - Samuel Tardieu ([@samueltardieu](https://github.com/samueltardieu)) - Daniel Bergey ([@bergey](https://github.com/bergey)) - Jim Kleckner ([@jkleckner](https://github.com/jkleckner)) - John Snow ([@jnsnow](https://github.com/jnsnow)) - Peter Maydell ([@pm215](https://github.com/pm215)) - Angus Salkeld - Hannes Eder - Junio C Hamano ([@gitster](https://github.com/gitster)) - Konstantin Khlebnikov ([@koct9i](https://github.com/koct9i)) - Mikhail Terekhov ([@termim](https://github.com/termim)) - Miklos Vajna - Sam Vilain ([@samv](https://github.com/samv)) - Shinya Kuribayashi - Ted Pavlic ([@tpavlic](https://github.com/tpavlic)) - Toby Allsopp - Andrew Chambers ([@andrewchambers](https://github.com/andrewchambers)) - Chris Packham ([@cpackham](https://github.com/cpackham)) - George Dunlap - Greg Kurz ([@gkurz](https://github.com/gkurz)) - Ilpo Järvinen ([@ij1](https://github.com/ij1)) - Jakob Stoklund Olesen ([@stoklund](https://github.com/stoklund)) - Jason Green ([@JasonGreen](https://github.com/JasonGreen)) - Jerry Snitselaar ([@snits](https://github.com/snits)) - Jesse Brandeburg ([@jbrandeb](https://github.com/jbrandeb)) - Juergen Wieferink - Kirill Smelkov ([@navytux](https://github.com/navytux)) - Norbert Nemec ([@NNemec](https://github.com/NNemec)) - Paulius Zaleckas ([@pauliuszaleckas](https://github.com/pauliuszaleckas)) - Pete Wyckoff - Peter Osterlund - Petr Baudis - Pierre Ossman - Roland Dreier - Sima Baymani - Stepan Koltsov - Toke Høiland-Jørgensen ([@tohojo](https://github.com/tohojo)) - Trond Myklebust - Topher Brown ([@topher200](https://github.com/topher200)) - Frank Benkstein ([@fbenkstein](https://github.com/fbenkstein)) stgit-2.6.0/CHANGELOG.md000066400000000000000000001442521520252120500144640ustar00rootroot00000000000000# Changelog ## 2.6.0 2026-05-18 ### Added - feat(rebase): add --exec option to run commands after each patch - feat: respect core.commentChar setting for escaping comment characters in commit messages ### Fixed - fix(refresh): handle "copied" status (#615) - fix(import): respect --name verbatim, ignoring stgit.namelength (#623) ### Changed - chore: bump MSRV to 1.85 - chore: update clap to 4.6 - chore: update gix to 0.83 - chore: update winnow to 1.0 - chore: update dependencies - docs: Update copyright year ## 2.5.5 2025-11-10 ### Fixed - fix(squash): keep author when squashed commits have same author ### Changed - chore: update gix to 0.74 ## 2.5.4 2025-08-10 ### Fixed - stgit.el: Use `with-eval-after-load` instead of a homemade version - stgit.el: Use `advice-add` instead of `defadvice` - stgit.el: Fix various checkdoc warnings - stgit.el: Support Emacs versions < 31 - stgit.el: Move 'stgit-patch-status-face-alist' before first use - stgit.el: Silence warnings of missing vc variables - stgit.el: Replace ad-hoc `make-local-variable` with `defvar-local` - stgit.el: Use defvar-local instead of make-local-variable - stgit.el: Enable lexical-binding - stgit.el: Allow empty descriptions - stgit.el: Add "--no-color" flag to 'git log' and 'git show' - stgit.el: Pass patch into `stgit-process-files` ### Changed - chore: update gix to 0.73 - docs: Update copyright year - feat(bash): complete patches from chosen branch ## 2.5.3 2025-02-22 ### Added - build: statically linked packages for riscv64 ### Changed - chore: update dependencies - refactor(stgit.el): use space-based indentation consistently ## 2.5.2 2025-02-16 ### Fixed - fix(stgit.el): various compile warnings - fix(stgit.el): Replace depercated cl function calls with new style - fix(stgit.el): checkdoc warnings - fix(stgit.el): emacs pre-pending "Summary: " to log-edit buffers ### Changed - chore: update jiff to 0.2.0 - chore: update winnow to 0.7.2 - chore: resolve winnow deprecations - chore: update dependencies ## 2.5.1 2025-01-18 ### Fixed - fix: assure branch creation respects fetch-specs of remotes (#522) ### Changed - ci: ubuntu-24.04 is now used to build release binaries - chore: gix is updated to 0.70 ## 2.5.0 2025-01-01 ### Added - feat: new "name" subcommand - feat: support calling stg rebase without arguments ### Fixed - docs: explain stgit.autosign a bit better ### Changed - feat: organize subcommands by group in help ## 2.4.13 2024-12-14 ### Fixed - fix(squash): preserve consensus author ### Changed - chore: update gix to 0.68 ## 2.4.12 2024-09-08 ### Changed - feat(push): revert overzealous modified status - updated dependencies ## 2.4.11 2024-08-25 ### Fixed - fix(push): report modified patches in output (#464) ### Changed - feat(push): colorize push status string - chore: update gix to 0.66 - feat: use jiff instead of time - feat: use winnow instead of nom - updated other dependencies ## 2.4.10 2024-08-17 ### Fixed - fix(import): --reject should create empty commit (#471) - docs(changelog): repair heading ### Changed - updated dependencies ## 2.4.9 2024-07-28 ### Changed - feat(rebase): do not rebase to same base - feat(rebase): show ref names of rebase target - chore: update gix to 0.64.0 ## 2.4.8 2024-07-21 ### Fixed - fix(refresh): handle edited message and patch name (#470) - fix: harden "stg rebase -i" against patches with multi-line subjects - fix: prefer --authdate over patch time with author ### Changed - updated dependencies ## 2.4.7 2024-05-05 ### Fixed - docs(pop): clarify --spill behavior (#445) - fix(branch): disallow branch before subcommand (#447) ### Changed - refactor: get gix-command via gix with command feature - Update gix to version 0.62 ## 2.4.6 2024-04-07 ### Fixed - fix(bash): fix completion for "committish" ### Changed - docs: Update copyright year - chore: update gix to 0.61.1 - ci: update to wix 4.0.5 ## 2.4.5 2024-02-18 ### Fixed - fix: stdout from hooks (#418) ### Changed - chore: add category and keywords to Cargo.toml - build: exclude some paths from crate - docs(readme): enumerate more package repositories - chore: update dependencies ## 2.4.4 2024-02-11 ### Fixed - fix: pass stdio for interactive editing (#415) - fix: update gix-tempfile and gix-lock to 13.1.0 (#413) ### Changed - chore: update dependencies ## 2.4.3 2024-02-04 ### Added - feat(branch): allow delete of current branch ### Fixed - fix(branch): delete branch config with branch - fix: use gix-command for interactive edit (#407) - fix: improved interactive editor diagnostics - chore: update gix to 0.58.0 (#407) - docs: fix dates in changelog ### Changed - refactor(branch): use gix to rename config section - refactor: use gix to remove stgit branch config - refactor: use gix-command for hooks - refactor: use non-deprecated indexmap methods - ci: update cargo-generate-rpm to 0.14.0 - ci: update to upload-artifact@v4 - ci: restore use of IO::Pty in MacOS build ## 2.4.2 2023-12-26 ### Changed - feat(pop): allow unescaped negative patch offsets - feat(show): allow unescaped negative patch offsets - chore: update dependencies ## 2.4.1 2023-12-10 ### Fixed - fix(zsh): short -r opt for `stg series` ### Changed - chore: update gix to 0.56.0 - chore: update transient dependencies ## 2.4.0 2023-10-08 ### Added - feat(delete): --all -A -U -H options - feat(sink): -T/--above option - feat(branch): short opts for clone and delete ## 2.3.3 2023-10-04 ### Fixed - fix(zsh): -S option for float, import, and sync - build: avoid non-portable install options - test: improved test script portability ### Changed - update dependencies ## [2.3.2] 2023-08-19 ### Fixed - fix!(uncommit): check for HEAD/top mismatch (#360) - docs: docstring spelling and formatting fixes ### Changed - feat(uncommit): print uncommited patches - pin serde to avoid using precompiled binary - update dependencies ## [2.3.1] 2023-07-25 ### Fixed - fix(zsh): typo in completion help for stg commit --all - fix: use canonical Message-ID spelling - fix(stgit.el): recognize new empty patch marker - fix(import): Keep first line break in body ### Changed - update dependencies ## [2.3.0] 2023-05-25 ### Removed - import-compressed is always enabled, no longer a feature ### Added - unofficial deb and rpm packages - msi package for Windows ### Fixed - fix(import): would panic without import-url feature - fix(import): patch numbers not stripped from name ### Changed - use bzip2-rs instead of bzip2 crate - update dependencies ## [2.2.4] 2023-05-15 ### Added - feat: Upgrade from ancient stack state formats (#235) ### Fixed - fix(branch): create based on remote branch (#317) - fix(import): lost subject lines resembling header (#321) - fix(import): subject line may be discarded ### Changed - chore: update dependencies ## [2.2.3] 2023-04-26 ### Fixed - fix: error using on Windows (#273) - fix: path handling for Windows compatibility - fix: commit-msg hook run from work root - fix: avoid "stg.exe" in usage on Windows - fix: use gitattributes to force LF endings on Windows - fix: wrap hooks with sh on Windows ### Changed - chore: update to gix 0.44.0 - chore: update other dependencies ## [2.2.2] 2023-04-01 ### Fixed - fix: rebase with '@' in ref names (#306) - fix: improved error messages for unrecognized commands ## [2.2.1] 2023-03-29 ### Changed - chore: update to clap 4.2.0 - chore: update to gix 0.43.0 - chore: pin clap minor version ### Fixed - fix(branch): allow reuse of partially deleted branch names (#290) - fix(branch): branch list alignment - fix: running hooks from worktree subdir (#295) - fix: running from linked worktree (#297) - fix(float): correct -S in usage string - fix: correctly show bold command/subcommand in overidden usage ## [2.2.0] 2023-02-24 ### Removed - feat!: remove short -s option for --submodules - fix!: patch name cannot be {base} or @ ### Added - feat: patch locator syntax - feat: locate branches using @{-N} syntax - feat(series): Add --reverse option - feat(series): options for patch offsets and indices - feat(series): --no-xxx options to override display options - feat(series): optional value for --short - feat!: short -s option for --signoff (#245) - feat(init): add -b/--branch option ### Changed - fix!: use -S as short opt for --series - feat!: constrain refresh -p to visible patches - feat(series)!: empty patch prefix changed to * - feat!: spell errors in lowercase - refactor: use gitoxide instead of git2 - refactor: use time crate instead of chrono - feat!: update to clap 4.1 - chore: update to latest dependencies ### Fixed - fix: Error if author or committer is not configured - fix: Use correct base directory for core.hooksPaths - fix(rename): colliding patch names - fix(rebase): repair rebasing to a tag (#265) - fix(branch): switch branch with detached head - docs: Repair docstrings being confused as html - docs: normalized spelling for --branch value ## [2.1.0] 2022-12-12 ### Added - feat: Configurable push conflict policy (#60) - feat: Add --committer-date-is-author-date option (#47) - feat(import): Add --3way option (#36) - feat(import): Add --directory option (#36) ### Changed - feat!: Relaxed stack initialization (#238) - feat!: Only sign stack based on stgit.gpgsign (#238) - fix!: Allow "---" separator in messages (#243) - feat: More descriptive push conflict message (#60) - feat: Avoid post-edit commits when no change - chore: Update dependencies to latest versions ### Fixed - fix: Improved error message for uninitialized stack - fix: Improve error for re-initialization attempt - fix(prev): Different error message for empty stack - fix: Accept full ref name for branches - fix(zsh): Complete --edit and --diff for stg new ## [2.0.4] 2022-11-30 ### Changed - docs: Document configuration variables - refactor: Use is-terminal instead of atty - chore: Update Cargo.lock with latest dependencies. ### Fixed - fix: Don't generate new patch name until after edit (#239) - fix: Run shell aliases from top-level of work tree - fix: Use GIT_PREFIX in built-in aliases ## [2.0.3] 2022-11-21 ### Changed - chore: Update Cargo.lock with latest dependencies. ### Fixed - fix: improved git version parsing on MacOS - fix: StGit-specific branch config handling - docs: fixed many typos ## [2.0.2] 2022-11-17 ### Changed - chore: Update Cargo.lock with latest dependencies. - docs(init): Add long help for `stg init`. ### Added - feat: Enable basic support for `extensions.worktreeconfig` to unblock sparse checkout with partial clone (#195). ### Fixed - docs: More inter-command links - docs: Normalize quoting ## [2.0.1] 2022-11-07 ### Changed - chore: Update to clap 4.0.22 ### Fixed - docs(readme): Clarify static versus dynamic linking (#230) - build: Improve Documentation build performance (#229) ## [2.0.0] 2022-11-06 ### Removed - `stg clone` is removed. Use `git clone` and `stg init` instead. - `stg mail` is replaced with `stg email format` and `stg email send`. - `stg refresh --spill` is replaced with dedicated `stg spill` command. - `stg edit` no longer accepts `-O/--diff-opts`. Custom diff options is in conflict with editable diffs since many (most?) diff options cause the diff to no long be applicable. - `stg files` no longer accepts `-O/--diff-opts`. This option was of marginal value since it only had a possible side effect when `--stat` was being used. ### Added - `stg id` now accepts the `-b/--branch` option. - `stg completion` command provides runtime support for shell completions. - `stg completion bash` generates bash shell completion script. - `stg completion fish` generates fish shell completion script. - `stg completion zsh` outputs zsh shell completion script. - `stg completion list` shows StGit commands and aliases and is used at completion-time by shell completion scripts. - `stg completion man` generates man pages in asciidoc format. - `stg email format` wraps `git format-patch` and provides a mechanism to generate patch emails and optional cover letter in mbox format. - `stg email send` wraps `git send-email` and allows sending patch emails, either from files generated by `stg email format` or by specifying patches directly. - `stg new --refresh` allows a new patch to be refreshed with changes in one step. The `-i/--index`, `-F/--force`, `-s/--submodules`, and `--no-submodules` options from `stg refresh` are also available to `stg new` when using `-r/--refresh`. - `stg series` gains the `-i/--commit-id` option to display patches' commit ids. - `stg show` diff output can now be limited to certain paths by specifying path limits on the command line. - `stg spill` replaces `stg refresh --spill`. - `stg version` gains `-s/--short` flag to show shortened version info. - Added documentation for patch range syntax to stg(1) man page. - Added `install-all` target to top-level Makefile that installs the executable, man pages, html pages, and shell completions. ### Changed - StGit is now implemented entirely in Rust instead of Python. - StGit is generally much faster; many commands are up to 4x faster. There was an emphasis on making informational commands such as `stg id`, `stg series`, and `stg top` as fast as possible to make their use in interactive contexts (shell prompts, IDE extensions) more comfortable. - StGit error messages have been updated; many have different, and hopefully better, wording. Error messages are also use color (when color is enabled). Scripts relying on exact error messages from StGit will need to be updated. - StGit output to stdout is generally more terse. Commands that change the stack such as `push`, `pop`, and `commit`, use sigils to denote the changes made to the stack. E.g. `stg commit p0..p3` will output `$ p0..p3` where the "$" sigil means that a patch, or patch range, has been committed. These are all the currently used stack change sigils: - `+` patch was pushed - `-` patch was popped - `>` patch became the current topmost patch - `&` patch was updated - `$` patch was committed - `#` patch was deleted - `@` patch was rolled-back - `!` patch was hidden - StGit aliases are now more like Git aliases. Normal aliases refer to StGit subcommands, but aliases prefixed with '!' are shell aliases that may run arbitrary commands. An example normal alias would be `git config stgit.alias.list 'series --description --empty'`. An example shell alias would be `git config stgit.alias.st '!git status --short'`. - Commands such as `stg goto`, `stg push`, and `stg pop` now require full/correct patch names on the command line and no longer accept unambiguous patch name prefixes. When an inexact patch name is provided on the command line, the error message will now suggest similar valid patch names. - Additional template search paths were added. In addition to looking for template files in .git/, also look in `$XDG_CONFIG_HOME/stgit/templates/` and `$HOME/.stgit/templates`. This search strategy is consistent with how git looks for the global config file. - The new `--signoff` patch edit option supersedes the deprecated `--sign` and `--sign-by` options. `--signoff` without its optional value does the same thing as `--sign`, while `--signoff=` does the same thing as `--sign-by=`. - The `--ack` and `--review` patch edit options now optionally take a value. The `--ack-by` and `--review-by` options are deprecated. - `stg branch` output is now generally less verbose. - `stg branch --describe` replaces `stg branch --description`. The `--description` subcommand remains supported as a hidden alias to `--describe`, but the description string must now be provided as its own argument; i.e. `--description="description string"` is no longer supported. - `stg branch --list` now produces colorized output. The `--color` option or `NO_COLOR` environment variable may be used to affect this behavior. - `stg branch --rename` now supports renaming regular git branches in addition to StGit-enabled branches. - `stg clean` now uses `-A` and `-U` short options for `--applied` and `--unapplied` instead of `-a` and `-u`. This is done for consistency with `stg series` and `stg show`. - `stg import` now only recognizes compressed patches by their file extension (`.bz2` or `.gz`) and no longer proactively attempts to decompress using all known decompressors. - `stg import` support for compressed input files is selectable at compile time using the `import-compressed` feature. - `stg import` support for importing from a URL is selectable at compile time using the `import-url` feature. **N.B.** there is a measurable runtime performance impact of building with `import-url` due to the unconditional, pre-main initialization of `curl` which affects **all** `stg` commands. - `stg log` now colorizes output by default. The `--color` option or `NO_COLOR` environment variable may be used to affect this behavior. - `stgit.new.verbose` changed to `stgit.edit.verbose` and now also affects edit behavior for `edit`, `refresh`, and `squash` along with `new`. - `stg new` now accepts `-e/--edit` and `-d/--diff` instead of `-v/--verbose` - `stg pick` now allows a mix of commits and patches to be picked whereas previously only a single commit xor multiple patches could be picked. - `stg pick` now performs a single stack transaction for all the picked patches/commits instead of one transaction per pick. - `stg push` now attempts to perform three-way merges, which may improve conflict resolution in some cases. This feature is enabled by default when git >= 2.32.0 is detected. - `stg rebase --interactive` the "squash" and "fixup" instructions may no longer be applied to the first patch in the instruction list. The stated semantics of both "squash" and "fixup" is that they squash the labeled patch with the preceding patch, which is not possible/valid when there is no preceding patch. - `stg refresh` no longer has a `--spill` flag. Use `stg spill` instead. - `stg series` has updated colorized output. - `stg series` now requires patch range arguments to be both in-order and contiguous. Constraining patch ranges in this manner ensures that the output from `stg series` is always a valid/correct view of a subset of the series. - `stg show` diff output respects the `--color` option. - `stg squash` now allows the full suite of patch edit options, including `-d/--diff`. Previously only a few message-related options were available. - `stg version` now displays copyright and license statements. ### Fixed - `stg branch --create` inherits the current branch's remote branch configuration, if available. The Python implementation had an apparent bug that prevented inheriting the remote branch configuration when creating from the current branch. - Avoid case insensitive patch name collisions. On operating systems with case-insensitive paths, patch names that only differ by case lead to patch reference collisions. StGit now ensures that patch names are distinct under case insensitive comparisons. - `stg pull` and `stg rebase` record updated stack state instead of deferring until the next stack-modifying command to do so. ### Changed since 2.0.0-rc.2 #### Changed - chore: Update Cargo.lock #### Fixed - fix(zsh): Repair broken completion of --git-opt - fix(zsh): Add missing `stg email send --branch` - fix(email): Send using --branch option - fix: Avoid duplicate signoff with stgit.autosign - fix: Do not use 3way for merged checks ## [2.0.0-rc.2] 2022-10-23 ### Changed - The `--diff-opts` option is renamed to `--diff-opt`. `--diff-opts` remains available as an alias. - The `--diff-opt` option no longer allows multiple git options per occurrence. This allows git diff options with spaces in their values. - The `--git-opts` option for `stg email format` and `stg email send` is renamed `--git-opt`. - The `--git-opt` option no longer allows multiple git options per occurrence. This allows git options with spaces in their values. - Zsh completion for `--diff-opt` and `--git-opt` leverage the full-featured git completion capability. ### Fixed - Repair check for modifications to stack by external tools. - `stg pull` and `stg rebase` record updated stack state instead of deferring until the next stack-modifying command to do so. - Improve patch application with `git apply --3way` when pushing` (#225) - Zsh completion for `--diff-opt` accommodates multiple occurrences ## [2.0.0-rc.1] 2022-09-30 ### Added - Added `--annotate` flag to `stg email send`. - Added `-p`/`--patch` option to `stg show` as alternative way to select patch ranges (#216). - Added `-n`/`--name` option to `stg new` as alternative way to specify new patch name (#216). ### Changed - Update `git2` to 0.15.0, which may further help compatibility with sparse checkouts and multiple worktrees (#195). - Update to `clap` 4.0, which changes the help formatting and coloring. - Update other dependencies to latest versions in Cargo.lock. - No longer depend on `lazy_static` crate. - Use `std::thread::scope` instead of custom mechanism. This brings the total number of uses of `unsafe` in StGit to zero. - Minimum rustc requirement is set to 1.63.0. - The '$' sigil used for committed patches is now yellow instead of white. - Patch names beginning with a hyphen '-' may be disambiguated from command line options by escaping the leading '-' with a backslash. - `stg email format` and `stg email send` now use `-G`/`--git-opts` to pass additional options to `git format-patch` and `git send-email`. - Patch name arguments to `stg email format` and `stg email-send` can now be placed after a `--` separator (#216). - Update top-level usage help for `stg`. ### Fixed - Various errors that may occur when executing a stack transaction are now handled more robustly such that the changes from the transaction are rolled-back so that the stack, repository, and worktree are all in a consistent state (#205). - The `stg uncommit -h` usage indentation is repaired. - The `stg float` usage now shows the two distinct usage modes. - `stg squash --name` allows patch names with leading '-'. - `stg diff --range` allows patch names and ranges with leading '-'. - Fix some pre-indented paragraphs in help/about strings. - Zsh completion for `stg edit` incorrectly included -O/--diff-opts. - Zsh completion for `stg files` incorrectly included -O/--diff-opts. ## [2.0.0-beta.3] 2022-08-28 ### Added - Add install targets for `contrib/` directory. ### Changed - Use `git` executable instead of `libgit2` for all status and index operations to improve compatibility with sparse index checkouts (#195). - Show commit hash in `stg version` output when not built from tag. - Use `cargo --locked` consistently in Makefiles. - Use "patch" extension in temp file name when editing a patch with a diff. - Updated transient dependencies in Cargo.lock. ### Fixed - Repair `stg branch --describe` panic when run without arguments - Repair zsh completions for `git branch` - Repair `stgit.el` to use compatible `stg show` commands (#202). - Repair `stg uncommit --to` to work with annotated tags (#203). - Repair `make install` to not install cargo tracking files. ## [2.0.0-beta.2] 2022-08-05 ### Changed - Improved error when push conflicts with untracked files (#193) - Removed a few transitive dependencies by turning-off features in bstr and chrono. - Update Cargo.lock with latest dependencies - Update to clap 3.2 and only use non-deprecated interfaces ### Fixed - Repair `stg spill` when spilling newly added files and using path limits. ## [2.0.0-beta.1] 2022-07-28 ### Removed - Removed Python implementation of StGit. ### Added - Man page generation in asciidoc format with `stg completion man`. This was needed for feature parity with the Python implementation. - Added documentation for patch range syntax to stg(1) man page. - Added `install-all` target to top-level Makefile that installs the executable, man pages, html pages, and shell completions. ### Changed - Additional template search paths were added. In addition to looking for template files in .git/, also look in `$XDG_CONFIG_HOME/stgit/templates/` and `$HOME/.stgit/templates`. This search strategy is consistent with how git looks for the global config file. - Makefile targets are updated such that they are all applicable to the Rust implementation. - Argument value names are now all lowercase in help and man pages. - Updated Cargo.lock with latest versions of dependencies. - Release checklist is updated for Rust implementation. ### Fixed - Minor typo fixes in help strings - Improved documentation for top-level `stg` options. - Improve error message in edge case of attempting to push a hidden patch by name when there are no unapplied patches. ## [2.0.0-alpha.2] 2022-07-07 ### Added - `stg email format` wraps `git format-patch` and provides a mechanism to generate patch emails and optional cover letter in mbox format. - `stg email send` wraps `git send-email` and allows sending patch emails, either from files generated by `stg email format` or by specifying patches directly. ### Changed - Bash completions for shell aliases now fallback to filename completions (#191). - Help options listings now ensure --color and --help are shown last. - Various zsh completion improvements: - Add descriptions for --color values - Complete -O/--diff-opts values (using `git diff-tree --git-completion-helper`) - Comprehend `stg -C ` options - Improved/corrected alias expansion - Improved error messages when completion is attempted outside git repo and/or StGit-initialized branch - Patch name completions now look and feel like output from `stg series` - Complete patch range syntax ('patch0..patchN') for all relevant commands - Completion for `stg squash` no longer allows duplicate patch name arguments - Removed completions for removed `stg mail` command - Completion for `stg sink` no longer offers hidden patches - Completion for `stg rename` comprehends second, new patch name argument - Completion for `stg diff --range` now works ### Fixed - Compatibility with git versions prior to 2.35.0 is repaired by avoiding using `git apply --allow-empty` (#192). - Fish completions for -O/--diff-opts are repaired ## [2.0.0-alpha.1] 2022-06-17 ### Added - `stg series` gains the `-i/--commit-id` option to display patches' commit ids. - `stg series` colorized output is modified. The main change is that patch descriptions are no longer yellow. - `stg version` now displays copyright and license statements. - `stg version` gains `-s/--short` flag to show shortened version info. - The `stgit.diff-opts` configuration variable is now respected as it was in the Python implementation. - `stg completion` command provides runtime support for shell completions. - `stg completion bash` generates bash shell completion script. - `stg completion fish` generates fish shell completion script. - `stg completion zsh` outputs zsh shell completion script. - `stg completion list` shows StGit commands and aliases and is used at completion-time by shell completion scripts. ### Changed - The `-O/--diff-opts` flag now allows both multiple space separated opts in one value as well as multiple occurrences of `-O/--diff-opts` on the same command line. This behavior is compatible with the Python implementation. - `stg series` help output splits options into a few sections. - Dependencies are updated to more recent versions in Cargo.lock. ### Fixed - `stg edit --set-tree` no longer causes the interactive editor to be implicitly invoked. - Repair build for non-Linux unix targets (including MacOS) and Windows targets. - Avoid case insensitive patch name collisions. On operating systems with case-insensitive paths, patch names that only differ by case lead to patch reference collisions. StGit now ensures that patch names are distinct under case insensitive comparisons. - Add missing `-t` short option for `--set-tree` for `stg edit`. - Add missing `-k` short option for `--keep`. ## [2.0.0-alpha.0] 2022-05-17 ### Removed - `stg edit` no longer accepts `-O/--diff-opts`. Custom diff options is in conflict with editable diffs since many (most?) diff options cause the diff to no long be applicable. - `stg files` no longer accepts `-O/--diff-opts`. This option was of marginal value since it only had a possible side effect when `--stat` was being used. - `stg clone` is removed (at least for the time being). Use `git clone` and `stg init` instead. - `stg mail` is removed, but will be re-added or replaced prior to the 2.0.0 release. ### Added - `stg new --refresh` allows a new patch to be refreshed with changes in one step. The `-i/--index`, `-F/--force`, `-s/--submodules`, and `--no-submodules` options from `stg refresh` are also available to `stg new`. - `stg id` now accepts the `-b/--branch` option. - `stg spill` replaces `stg refresh --spill`. ### Changed - StGit aliases are now more like Git aliases. Normal aliases refer to StGit subcommands, but aliases prefixed with '!' are shell aliases that may run arbitrary commands. An example normal alias would be `git config stgit.alias.list 'series --description --empty'`. An example shell alias would be `git config stgit.alias.st '!git status --short'`. - The `--ack` and `--review` options now optionally take a value. The `--ack-by` and `--review-by` options are deprecated. - Commands such as `stg goto`, `stg push`, and `stg pop` now require full/correct patch names on the command line and no longer accept unambiguous patch name prefixes. When an inexact patch name is provided on the command line, the error message will now indicate similar valid patch names. - `stg branch` output is now generally less verbose. - `stg branch --describe` replaces `stg branch --description`. The `--description` subcommand remains supported as a hidden alias to `--describe`, but the description string must now be provided as its own argument; i.e. `--description="description string"` is no longer supported. - `stg branch --list` now produces colorized output. The `--color` option or `NO_COLOR` environment variable may be used to affect this behavior. - `stg branch --rename` now supports renaming regular git branches in addition to StGit-enabled branches. - `stg clean` now uses `-A` and `-U` short options for `--applied` and `--unapplied` instead of `-a` and `-u`. This is done for consistency with `stg series` and `stg show`. - `stg import` now only recognizes compressed patches by their file extension (`.bz2` or `.gz`) and no longer attempts to decompress using all known decompressors. - `stg import` support for compressed input files is selectable at compile time using the `import-compressed` feature. - `stg import` support for importing from a URL is selectable at compile time using the `import-url` feature. - `stg log` now colorizes output by default. The `--color` option or `NO_COLOR` environment variable may be used to affect this behavior. - `stgit.new.verbose` changed to `stgit.edit.verbose` and now affects edit behavior for `edit`, `refresh`, and `squash` along with `new`. - `stg new` now accepts `-e/--edit` and `-d/--diff` instead of `-v/--verbose` - `stg pick` now allows a mix of commits and patches to be picked whereas previously only a single commit xor multiple patches could be picked. - `stg pick` now performs a single stack transaction for all the picked patches/commits instead of one transaction per pick. - `stg rebase --interactive` the "squash" and "fixup" instructions may no longer be applied to the first patch in the instruction list. The stated semantics of both "squash" and "fixup" is that they squash the labeled patch with the preceding patch, which is not possible/valid when there is no preceding patch. - `stg refresh` no longer has the `--spill` flag. Use `stg spill` instead. - Updated colorized output for `stg series`. - `stg series` now requires patch range arguments to be both in-order and contiguous. Constraining patch ranges in this manner ensures that the output from `stg series` is always a valid/correct view of a subset of the series. - `stg show` diff can now be limited to certain paths by specifying path limits on the command line. - `stg show` diff output respects the `--color` option. - The new `--signoff` patch edit option supersedes the deprecated `--sign` and `--sign-by` options. `--signoff` without its optional value does the same thing as `--sign`, while `--signoff=` does the same thing as `--sign-by=`. - `stg squash` now allows the full suite of patch edit options, including `-d/--diff`. Previously only a few message-related options were available. ### Fixed - `stg branch --create` inherits the current branch's remote branch configuration, if available. The Python implementation had an apparent bug that prevented inheriting the remote branch configuration when creating from the current branch. ## [1.5] 2022-01-28 ### Removed ### Added - Add Makefile targets for installing shell completions - `stg rebase --interactive` learns 'hide' instruction ### Changed - Picked patch names are preserved when possible (#175) - Replace `--unapplied` option with `--noapply` for `stg pick` (#174) - `stg pick --noapply` no longer reverses patch order (#174) - Use `stg version` uses `sys.executable` to get Python version. ### Fixed - Repair `stg repair` with amended first patch (#163) - Repair corner cases where invalid patchnames could be generated by `stg new`, `stg uncommit`, etc. (#176) - `stg mail` could crash due to a misspelled reference (#178) - Zsh completion for `stg refresh -p` now completes against all patches (not just applied patches). - Zsh gains missing completion for `stg push --noapply` - Minor repair to help for `stg float --noapply` and `stg push --noapply` - Restore `stg sink --nopush` capability. ## [1.4] 2021-10-27 ### Removed - Python 3.5, which became EOL 2020-09-13, support is deprecated and will be removed in a future StGit release - Python 3.6, which will be EOL 2021-12-23, support is deprecated and will be removed in a future StGit release ### Added - The new `stg import --message-id` option causes the Message-ID from imported emails to be included as the Message-Id trailer in the patch description (#42) - The new 'stgit.import.message-id' config option also enables the Message-Id trailer (#42) ### Changed - `stg import` no longer creates "Message-Id" trailer by default when importing patches from email (#42) - StGit works with Python 3.10 - `stg version` prints a more abbreviated Python version - `stg commit` will no longer commit empty patches by default; the `--allow-empty` option may be used to override this behavior (#158) - The `stgit.main.main()` function now takes an argv parameter and returns an int return code in most cases instead of calling sys.exit(), thus making main() a bit easier to use as an API. ### Fixed - Repair stack upgrade with `stg branch --list` (#155) - Repair crash in `stg squash` with out of order patches and no name specified (#157) - Zsh completions learn `stg float --noapply` option - Zsh completion for `stg sink` now allows multiple patches ## [1.3] 2021-09-26 ### Removed ### Added ### Changed ### Fixed - Repair crash regression when using `stgit.autosign` ## [1.2] 2021-09-26 ### Removed ### Deprecated - Python 3.5, which became EOL 2020-09-13, support is deprecated and will be removed in a future StGit release - Python 3.6, which will be EOL 2021-12-23, support is deprecated and will be removed in a future StGit release ### Added - `stg rebase ` learns `--interactive`; easily re-order, edit, squash, fixup, or delete patches via your editor - `stg rebase` learns `--autostash`; stash changes before the rebase and apply them after. Also configurable with the `stgit.autostash` configuration option - `stg edit` can now rename patches (#119) - `stg edit` gains helpful instructions (#138) - `stg new` learns `--verbose`, which includes a diff in the editor window (similar to `git commit --verbose`). This behavior is also configurable with the `stgit.new.verbose` configuration option - `stg push` and `stg float` learn `--noapply` option; allows patches to be reordered without updating worktree and deferring merge conflict resolution (#144) - `stg edit`, `stg refresh`, and `stg new` learn the `--sign-by`, `--ack-by`, and `--review-by` options which allow those respective trailers' values to be specified by the user on the command line (#92) ### Changed - Stack metadata version 5; stack metadata is moved from `refs/heads/.stgit` to `refs/stacks/` and the stack metadata file now uses a JSON format instead of the prior custom format; the stack metadata will be upgraded to v5 on first use of this version of StGit; like all stack metadata upgrades, **this is a one-way auto-upgrade for existing stacks** (#65) - Use setuptools instead of distutils for packaging - No git or python version checks in setup.py - Use different dynamic versioning system - Install `stg` executable as console_script entry point - More sophisticated search for bash.exe on Windows when running hooks - The editor window text for `stg squash` has been modified to mirror git's behavior -- the squash edit message now includes all commits (#71) - Binary diffs are no longer shown when with `stg edit -d` - Multiple trailers can now be added at once; this is now allowed, for example: `stg edit --sign --review --ack` - Update zsh completion for `stg rebase` to show local and remote heads (#102) - Zsh completions for commands with patch arguments now comprehend the effect of `-b/--branch` and `-B/--ref-branch` - Zsh completions now guard patch names--one less TAB press to complete patch names in certain contexts - `stg import` now extracts the `Message-ID` email header into the patch message (#42) ### Fixed - Repair crash when attempting to export empty patch (#112) - Exact command name matches are unambiguous (#110) - Exiting with an empty `stg edit` editor will now abort the edit; previously it would delete your commit message. (#138) - Repair completions when stg.series.description is enabled in config - Workaround child process reaping race on Windows (#78) - Repair crash with `stg float --series` when bad patch name in series - Repair zsh completion for `stg float` to accept multiple patch names - Repair zsh completion for changed files, affecting `stg refresh` and `stg diff` ### Internal - Add link to coverage.io project to CONTRIBUTING.md - Set smart `exclude_lines` default for 'coverage' - Expanded test suite for `stg edit` - Add pkgtest.py script to help test StGit packaging - Cleanup .gitignore files ## [1.1] 2021-04-30 ### Removed ### Added - StGit GPG-signs patches when `commit.gpgsign` is set (#12) - Support `core.hooksPath` in git config - Add `-C` option for `stg import` and `stg fold` (#18) ### Changed - Allow importing mail and series from urls (#94) - `stg refresh --edit` may also use `--diff` and `--diff-opts` (#98) - `stg goto` allows sha1 of a patch instead of patch name (#93) ### Fixed - Repair hang in `stg pull -m`, `stg goto -m`, and `stg push -m` - Repair `stg mail` to show diffstat of whole series (#104) - Repair MANIFEST.in to include AUTHORS.md and README.md files ## [1.0] 2021-02-07 ### Removed - Drop support for Python < 3.5 - Remove previously deprecated `stg publish` command - Removed contrib scripts: `stg-swallow`, `stg-fold-files-from`, `stg-dispatch`, `stg-whatchanged`, and `stg-show-old` ### Added - The pre-commit hook is now run for `stg refresh` - New `--spill` option for `stg refresh` - Add stgit.series.description config option (#88) - Official support for Python versions up to 3.9 ### Changed - Stack metadata format 4. All metadata now kept in Git objects; no more stack state files in .git/patches. **A one-way auto-upgrade to format version 4 will occur when StGit commands are run on an existing StGit branch.** - Use `python3` in shebangs instead of `python` - `contrib/stgbashprompt.sh` is no longer executable - Internal docstrings now use reStructuredText instead of Epytext ### Fixed - Importing large patches is much, much faster (#66) - Other performance improvements when dealing with large patches - Repair diffstat when outside work tree root (#62) - Use encoded (string) environment variables on Windows (#79) - Fix `stg pull` when no upstream is configured (#83) - Fix `refresh` crash with path limiting and files added to index (#85) - Repair `new` with patchdescr.template crash (#87) - Repair `log` from worktree subdir with patches specified - Repair `import` allowing/generating duplicate patch names (#64) - Repair `mail --auto` to strip comments after addrs (#91) ## [0.23] 2020-06-12 ### Removed - Drop support for Python 3.3; Python 2 (2.6 and 2.7) remain deprecated, but supported for one last release - Tutorial is removed; it now exists as part of the website ### Deprecated - Python 2.x support is deprecated and will be removed in a future release ### Added - Support html5 output of docs from asciidoc - Add `--expose` option for `stg pick` to allow picked commit message to be customized ### Changed - Limit mail diffstat to 72 columns - Added pyproject.toml file for black configuration - Minimum Git version is 2.2.0 - Quote stg and subcommand in man page synopsis - Replaced RELEASENOTES with this CHANGELOG.md - Replaces Documentation/SubmittingPatches with CONTRIBUTING.md ### Fixed - Repair MANIFEST.in and generated source dist - Repair importing mail with ": " (colon space) in subject - Fix mail cover letter shortlog - Fix mail cover letter diffstat - `stg series` now only outputs colors when `isatty()` - Repair mail SSL check (#57) - Repair `stg mail` with both `-a` and `-e` options (#58) - Remove empty short-opt for `--no-submodules` of `stg refresh` - Repair build.py for Python 2 with explicit `flush()` - `stgit.refreshsubmodules` added to sample gitconfig ### Internal - Update docs build system from upstream Git docs - Use coverage contexts to map commands to covered lines - Improve mail tests - Use GitHub Actions instead of TravisCI - Format StGit source using black formatter ## [0.22] - 2020-03-02 ### Removed - Remove debian packaging; downstream Debian uses its own anyway ### Deprecated - Python 2.x support is deprecated and will be removed in the next StGit release - `stg publish` is deprecated and will be removed in the next StGit release ### Added - `stg import` has new --keep-cr option, like `git mailsplit` ### Changed - `stg new` now includes patch name in log message - `stg branch --rename` can now rename the current branch - `stg branch --create` now works even if the workspace is dirty, consistent with `git checkout` - `stg branch --description` now works on both regular and stgit branches - `stg edit --diff` now implies `--edit` - `stg refresh` and `stg edit` now reset the committer information, consistent with `stg push` - git notes are now preserved when patches are modified - Tutorial improvements - Many additional tests and test improvements - All stgit commands now use "new" git library infrastructure ### Fixed - `stg branch --create` inherits remote correctly from parent committish - Patch names are checked earlier to avoid inconsistent stack states - Improved commit data parsing and handling of non-UTF8 encodings - Repair git error messages when checking stgit version from outside a git repo ## [0.21] - 2019-10-28 ### Changed - Faster handling of large patches (#44) ### Fixed - Build reproducibility repairs (Thanks reproducible-builds.org team!) - Python can now be run with optimizations (`python -O`) - `stg log` now prints trailing newline - Improved command line option parsing for `stg log` ## [0.20] - 2019-10-04 ### Added - `stg patches -d` can now output colored diffs. - `stg publish --overwrite` allows branch to be overwritten instead of creating new commits. - `stg log --clear` deletes the stack's log history. Use with caution. - Fish shell completions for stg. - Zsh completions for stg. - `stg mail --domain` option overrides the host's domain in the message ID. ### Changed - Branch protection metadata now captured in config instead of .git/patches/protect file. This updates stgit's metadata format from v2 to v3. - `stg diff` no longer shows binary diffs by default. Use `-O--binary` or add `--binary` to stgit.diff-opts in config. - Diagnostic output is now routed to stderr instead of stdout. Diagnostic output is also now sent to stderr unconditionally, i.e. no more isatty() test (#35). - Converted to "new" lib infrastructure: `show`, `patches`, `diff`, `pick`, `pull`, `rebase`, and `fold`. ### Fixed - `stg show` detects conflicting --applied and --unapplied options. - `stg show --stat` now shows commit headers. - `stg patches --diff` now shows proper diff instead of `b'...'` repr of diff. - `stg diff --range` detects some invalid values (e.g. `-r ..`). - Date parsing is now more portable, only use platform specific `date` as last parsing option. Affects, e.g., `stg refresh --authdate`. - Repaired search path for templates to avoid looking in Python site-packages directory. - Ensure stdout and stderr are flushed. Rarely affected `stg diff`. - `stg repair` will now fail if extra command line arguments are provided. - Bash completions are now generated in a reproducible manner. - `stg edit --diff` on an empty patch no longer crashes. - `stg pick` no longer fails when picked commit has empty message (#39). - `stg rebase` no longer crashes when there are conflicts (#34). - `stg pick` no longer crashes if --name is not provided when picking a regular commit object. - Improved test coverage for: branch, diff, pick, sync, - New tests for: files, patches, fold, series - Portable use of iconv, sort, and sed in tests. - Linting using flake8 and isort. - All Python code now conforms to PEP-8. - Updated test infrastructure from git 2.20. - Parallel tests with coverage (`make -j4 coverage`) now works. - Documentation build is not included in code coverage. - Repaired log end messages when using `STGIT_SUBPROCESS_LOG=debug`. - Renamed "dunder" instance attributes to improve debugging. - Fail faster when patch name has slash ('/') (#24). ## [0.19] 2018-11-05 ### Changed - Python 3 support. StGit supports Python 2.6, 2.7, 3.3, 3.4, 3.5, 3.6, and 3.7. PyPy interpreters are also supported. - Submodules are now ignored when checking if working tree is clean. Submodules are also not included by default when refreshing a patch. - Config booleans are now parsed similarly to git-config. - `contrib/stgit.el` is now licenced with GPLv2. - Add continuous integration (travis-ci) and code coverage (coveralls) support. - Many new test cases were added. ### Fixed - Repair handling of emails with utf-8 bodies containing latin-1 characters. Also correctly decode email headers containing quoted encoded words. - StGit's version is now correct/available in the release archive. ## [0.18] 2017-08-14 ### Added - `commit-msg` hook support for easier integration with Gerrit, allowing a Change-Id line to be inserted in the commit message - `stg mail` improvements for 'Suggested-by:' tag and auto generation of Cc for the cover letter based on all tags in the series - `stg mail` bash completion for the --to, --cc and --bcc options based on the content of the [mail "alias"] section of Git configuration - `stg edit --review` option to add a 'Reviewed-by:' tag - `stg pop --spill` functionality to allow popping a patch from the stack while keeping its modification in the tree ### Changed - Project page details updated (gna.org has been shut down) ### Fixed - Various fixes and test coverage improvements ## [0.17.1] 2013-09-30 ### Changed - Test suite improvements. - Print tracebacks to stderr. - Run test suite in parallel. ### Fixed - Fix dirty index errors when resolving conflicts. - Fix --authdate date parsing. ## [0.17] 2013-06-27 ### Added - `stg delete --top` option for deleting the top patch. - `stg branch --merge` option for merging the work tree changes into the other branch. - Support for sending patches both as attachment and inline. ### Changed - `stg mail` no longer filters explicitly added `--cc` sender address. - `stg refresh` warns when index is dirty. ### Fixed - Fix for parsing the commit header correctly. - Several `stgit.el` (Emacs mode) improvements. - Fix `stg status --reset` error messages. - HTML documentation fix. - Email template fixes. ## [0.16] 2012-01-09 ### Added - UI adjustments to better match the Git commands. - `stg status` is an alias for `git status`. - `stg reset --hard` behaves similarly to the corresponding git command and option. - `stg branch --cleanup` option to remove the StGit metadata for a given branch. - `stg mail` can use `git send-email` directly. - Vim syntax highlighting for StGit commit messages. ### Fixed - Several improvements to the Emacs mode (stgit.el). - Many bug-fixes. ## [0.15] 2009-10-24 ### Removed - The commands "stg add", "stg rm", "stg cp", and "stg resolved" were removed, since there are corresponding Git equivalents. ### Added - New core infrastructure for repository operations, including: - Infinite undo/redo operations and corresponding commands. - Automatic rollback of changes following a failed operation (using transactions)---this ensures that StGit commands either succeed or do nothing. Previously, every commands had its own ad hoc implementation of this. - Some commands were added, including - `stg squash`, for combining two or more patches into one. - `stg publish`, for maintaining merge-friendly branches (which are not rebased). - `stg prev/next` for printing the name of the previous or next patch in the series. - The `stg import` and `stg fold` commands support the `-p N` option for stripping leading slashes from diff paths. - The `stg import` and `stg fold` commands support the `--reject` option for leaving rejected hunks in corresponding `*.rej` files. - New patch identification syntax: `:` (see documentation for the "stg id" command). - Autosigning of imported patches when `sign.autosign` configuration option is set. - A powerful Emacs mode for StGit was added to the "contrib" directory. It displays the patch stack in an Emacs buffer, and can handle all common StGit tasks. - Man pages and an improved tutorial. ### Changed - Improved bash tab-completion, automatically generated from the stg command definitions. ## [0.14.3] 2008-06-08 ## [0.14.2] 2008-13-24 ## [0.14.1] 2007-12-11 ## [0.14] 2007-12-09 ## [0.13] 2007-07-26 ## [0.12] 2007-02-06 ## [0.11] 2006-10-21 ## [0.10] 2006-06-11 ## [0.9] 2006-04-07 ## [0.8] 2005-12-23 ## [0.7] 2005-10-02 ## [0.6] 2005-08-21 ## [0.5] 2005-07-30 ## [0.4] 2005-07-10 stgit-2.6.0/CONTRIBUTING.md000066400000000000000000000112101520252120500150670ustar00rootroot00000000000000# How to contribute Thank you for using and contributing to StGit! This brief guide describes how to contribute bug reports, feature ideas, and code changes to the Stacked Git project. ## Bugs StGit is not bug-free software. If you think you may have found a bug, please visit the [issue tracker](https://github.com/stacked-git/stgit/issues) and search to see if an issue for the bug has already been created. If a relevant issue already exists, you may want to subscribe to the issue so that you can be notified when the issue status changes. Also, you may want to add notes about the bug if your observations differ from the original issue. If an existing issue does not match, then you are encouraged to create a new issue. ### Creating an Issue When creating an issue, please refer to this checklist. The goal is to capture the relevant information about your environment and the actions that triggered the bug needed to debug the problem. Please include the following in StGit issue reports: 1. The output from `stg --version`, which includes StGit and Git versions. 2. What StGit command(s) triggered the problem. 3. Details about the StGit stack and the Git repository. ## Features Ideas for StGit features may be submitted on the [issue tracker][issue-tracker] for consideration and discussion. A proposed feature's value will be weighed against its reach to StGit users and its ongoing cost to StGit maintenance. High-reach, low-maintenance features are most likely to be accepted by StGit's maintainers. And for a StGit feature to be realized, it needs to be implemented. While it is *possible* that another member of the StGit community will champion your idea, the more you contribute, the more likely the feature will get done. So writing test cases, specifying details about the feature, and writing working code are all helpful toward getting a feature into StGit. [issue-tracker]: https://github.com/stacked-git/stgit/issues ## Code Changes Code changes for bug fixes and features should be submitted as [pull requests][PR] to the [stgit repository][stgit-repo] on GitHub, with the following guidelines: - Test cases! Please add test cases to the test suite in the `t` directory to verify any new or changed StGit behaviors. And run `make test` to ensure the test suite passes. - Use [Conventional Commit][conventional-commit] style commit messages. - Add a `Signed-off-by:` trailer to each commit message to indicate that certifies that you wrote or otherwise have the right to contribute the patch as open-source, according to the [Developers Certificate of Origin](#developers-certificate-of-origin-11). A `Signed-off-by:` line can be added to a patch by running `stg edit --sign`, and you can add one to new patches by default with the setting by setting the config `stgit.autosign` to `Signed-off-by`. - Lint. Run `make lint` to ensure that the code meets the project's syntactic standards and passes static checks. [PR]: https://help.github.com/en/github/collaborating-with-issues-and-pull-requests [stgit-repo]: https://github.com/stacked-git/stgit [conventional-commit]: https://www.conventionalcommits.org/ ### 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. ### Checklist - Each commit (patch) addresses a coherent topic. - `make lint` passes. - No commented-out code or unneeded files in commits. - Each commit has a meaningful commit message using the [Conventional Commit][conventional-commit] style. - Each commit has a `Signed-off-by: Your Name 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-1335 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 Library General Public License instead of this License. stgit-2.6.0/Cargo.lock000066400000000000000000001557771520252120500145760ustar00rootroot00000000000000# This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 4 [[package]] name = "adler2" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "allocator-api2" version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "anstream" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", "windows-sys 0.61.2", ] [[package]] name = "anyhow" version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "arc-swap" version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" dependencies = [ "rustversion", ] [[package]] name = "bitflags" version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "block-buffer" version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ "generic-array", ] [[package]] name = "block2" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ "objc2", ] [[package]] name = "bstr" version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ "memchr", "regex-automata", "serde", ] [[package]] name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" [[package]] name = "bzip2-rs" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "beeb59e7e4c811ab37cc73680c798c7a5da77fc9989c62b09138e31ee740f735" dependencies = [ "crc32fast", "tinyvec", ] [[package]] name = "cc" version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "clap" version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", "clap_lex", "strsim", "terminal_size", ] [[package]] name = "clap_lex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clru" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "197fd99cb113a8d5d9b6376f3aa817f32c1078f2343b714fff7d2ca44fdf67d5" dependencies = [ "hashbrown 0.16.1", ] [[package]] name = "colorchoice" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] name = "cpufeatures" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ "libc", ] [[package]] name = "crc32fast" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-utils" version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crypto-common" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ "generic-array", "typenum", ] [[package]] name = "ctrlc" version = "3.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" dependencies = [ "dispatch2", "nix", "windows-sys 0.61.2", ] [[package]] name = "curl" version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79fc3b6dd0b87ba36e565715bf9a2ced221311db47bd18011676f24a6066edbc" dependencies = [ "curl-sys", "libc", "openssl-probe", "openssl-sys", "schannel", "socket2", "windows-sys 0.59.0", ] [[package]] name = "curl-sys" version = "0.4.88+curl-8.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "644816de6547255eff4e491a1dda1c19b7237f00b62a61e6e64859ce4f2906d0" dependencies = [ "cc", "libc", "libz-sys", "openssl-sys", "pkg-config", "vcpkg", "windows-sys 0.61.2", ] [[package]] name = "dashmap" version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" dependencies = [ "cfg-if", "crossbeam-utils", "hashbrown 0.14.5", "lock_api", "once_cell", "parking_lot_core", ] [[package]] name = "digest" version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", ] [[package]] name = "dispatch2" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags", "block2", "libc", "objc2", ] [[package]] name = "dunce" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "encoding_rs" version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "equivalent" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys 0.61.2", ] [[package]] name = "faster-hex" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7223ae2d2f179b803433d9c830478527e92b8117eab39460edae7f1614d9fb73" dependencies = [ "heapless", "serde", ] [[package]] name = "fastrand" version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" [[package]] name = "filetime" version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", ] [[package]] name = "find-msvc-tools" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] name = "flate2" version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foldhash" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "foldhash" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] name = "generic-array" version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", ] [[package]] name = "getrandom" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" dependencies = [ "cfg-if", "libc", "r-efi", "wasip2", "wasip3", ] [[package]] name = "gix" version = "0.83.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce52001b946a6249d5d0d3011df0a042ac3f8a4d013460db6476577b0b9c567" dependencies = [ "gix-actor", "gix-archive", "gix-blame", "gix-command", "gix-commitgraph", "gix-config", "gix-date", "gix-diff", "gix-dir", "gix-discover", "gix-error", "gix-features", "gix-filter", "gix-fs", "gix-glob", "gix-hash", "gix-hashtable", "gix-index", "gix-lock", "gix-merge", "gix-negotiate", "gix-object", "gix-odb", "gix-pack", "gix-path", "gix-protocol", "gix-ref", "gix-refspec", "gix-revision", "gix-revwalk", "gix-sec", "gix-shallow", "gix-status", "gix-submodule", "gix-tempfile", "gix-trace", "gix-traverse", "gix-url", "gix-utils", "gix-validate", "gix-worktree", "gix-worktree-state", "gix-worktree-stream", "nonempty", "smallvec", "thiserror", ] [[package]] name = "gix-actor" version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "272916673b83714734b15d4ef3c8b5f1ccddb15fea8ff548430b97c1ab7b7ed8" dependencies = [ "bstr", "gix-date", "gix-error", ] [[package]] name = "gix-archive" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a20ec244b733338d4cb60e5e05eac700dab7fcc689647b1d1daa9396b119342" dependencies = [ "bstr", "gix-date", "gix-error", "gix-object", "gix-worktree-stream", ] [[package]] name = "gix-attributes" version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe17c5a1c0b6f2ef1476aa1d3222ea50cdff67608016613a58bfc3e078046000" dependencies = [ "bstr", "gix-glob", "gix-path", "gix-quote", "gix-trace", "kstring", "smallvec", "thiserror", "unicode-bom", ] [[package]] name = "gix-bitmap" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ecbfc77ec6852294e341ecc305a490b59f2813e6ca42d79efda5099dcab1894" dependencies = [ "gix-error", ] [[package]] name = "gix-blame" version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14dab9a942ab54a9661ded7397c3bf927274e7afa94494db0d75cfcbde02ca0a" dependencies = [ "gix-commitgraph", "gix-date", "gix-diff", "gix-error", "gix-hash", "gix-object", "gix-revwalk", "gix-trace", "gix-traverse", "gix-worktree", "smallvec", "thiserror", ] [[package]] name = "gix-chunk" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edf288be9b60fe7231de03771faa292be1493d84786f68727e33ad1f91764320" dependencies = [ "gix-error", ] [[package]] name = "gix-command" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86335306511abe43d75c866d4b1f3d90932fe202edcd43e1314036333e7384d8" dependencies = [ "bstr", "gix-path", "gix-quote", "gix-trace", "shell-words", ] [[package]] name = "gix-commitgraph" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe3b5aa0f24e19028c261d229aeeedafcaaa52ebd71021cc15184620fc9d32eb" dependencies = [ "bstr", "gix-chunk", "gix-error", "gix-hash", "memmap2", "nonempty", ] [[package]] name = "gix-config" version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c01848aebd21c67f6ba41f1de8efd46ae96df21f001954a3c9e1517e514d410" dependencies = [ "bstr", "gix-config-value", "gix-features", "gix-glob", "gix-path", "gix-ref", "gix-sec", "smallvec", "thiserror", "unicode-bom", ] [[package]] name = "gix-config-value" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b39ed39ee4c10a3b157f9fb94bac8098d9f8e56201f0cf7dee6c187416c4b2" dependencies = [ "bitflags", "bstr", "gix-path", "libc", "thiserror", ] [[package]] name = "gix-date" version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b94cdae4eb4b0f4136e3d9b3aa2d2cd03cfb5bb9b636b31263aea2df86d41543" dependencies = [ "bstr", "gix-error", "itoa", "jiff", "smallvec", ] [[package]] name = "gix-diff" version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc08e0fa1a91ff5f24affeab052f198056645e1de004910bde7b82b50ea5982a" dependencies = [ "bstr", "gix-command", "gix-filter", "gix-fs", "gix-hash", "gix-imara-diff", "gix-object", "gix-path", "gix-tempfile", "gix-trace", "gix-traverse", "gix-worktree", "thiserror", ] [[package]] name = "gix-dir" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a0fc06e9e1e430cbf0a313666976d90f822f461a6525320427aa9b8af5236c" dependencies = [ "bstr", "gix-discover", "gix-fs", "gix-ignore", "gix-index", "gix-object", "gix-path", "gix-pathspec", "gix-trace", "gix-utils", "gix-worktree", "thiserror", ] [[package]] name = "gix-discover" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17852e6a501e688a1702b24ebe5b3761d4719455bc869fd29f38b0b859bcad34" dependencies = [ "bstr", "dunce", "gix-fs", "gix-path", "gix-ref", "gix-sec", "thiserror", ] [[package]] name = "gix-error" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e207b971746ab724fccdfced2e4e19e854744611904a0195d3aa8fda8a110613" dependencies = [ "bstr", ] [[package]] name = "gix-features" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af375693ad5333d0a2c66b4c5b2cbe9ccc38e34f8e8bf24e4ae42c12307fdc4f" dependencies = [ "bytes", "crc32fast", "gix-path", "gix-trace", "gix-utils", "libc", "once_cell", "prodash", "thiserror", "walkdir", "zlib-rs", ] [[package]] name = "gix-filter" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac917dbe9653c9b615d248db91907a365bd779750c9e1b457a9d9fdeece3a08" dependencies = [ "bstr", "encoding_rs", "gix-attributes", "gix-command", "gix-hash", "gix-object", "gix-packetline", "gix-path", "gix-quote", "gix-trace", "gix-utils", "smallvec", "thiserror", ] [[package]] name = "gix-fs" version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e1967daac9848757c47c2aef0c57bcadc1a897347f559778249bf286a536c86" dependencies = [ "bstr", "fastrand", "gix-features", "gix-path", "gix-utils", "thiserror", ] [[package]] name = "gix-glob" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08bf29249a069bf2507f5964f80997f37b134d320ea348d66527726b9be2c38c" dependencies = [ "bitflags", "bstr", "gix-features", "gix-path", ] [[package]] name = "gix-hash" version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bcf70d1e252337eed16360f8b8ebb71865ece58eab7954b39ce38b420de703d2" dependencies = [ "faster-hex", "gix-features", "sha1-checked", "thiserror", ] [[package]] name = "gix-hashtable" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d33b455e07b3c16d3b2eeebc7b38d2dafcbf8a653de1138ef55d4c2a1fd0b08b" dependencies = [ "gix-hash", "hashbrown 0.16.1", "parking_lot", ] [[package]] name = "gix-ignore" version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6bb13fbbeeafee943e52b61fcc88dfddf6a452fcaf0c4d0cdc8f218fa25bbec5" dependencies = [ "bstr", "gix-glob", "gix-path", "gix-trace", "unicode-bom", ] [[package]] name = "gix-imara-diff" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39eb0623e15e4cb83c02ce6a959e48fadd1ae3b715b36b5acc01816e01388c82" dependencies = [ "bstr", "hashbrown 0.16.1", ] [[package]] name = "gix-index" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "54c3ef97ad08121e4327a6226bd63fed6b9e3c6b976d48bddd4356d9d41191db" dependencies = [ "bitflags", "bstr", "filetime", "fnv", "gix-bitmap", "gix-features", "gix-fs", "gix-hash", "gix-lock", "gix-object", "gix-traverse", "gix-utils", "gix-validate", "hashbrown 0.16.1", "itoa", "libc", "memmap2", "rustix", "smallvec", "thiserror", ] [[package]] name = "gix-lock" version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09b3bc074e5723027b482dcd9ab99d95804a53742f6de812d0172fbba4a186c1" dependencies = [ "gix-tempfile", "gix-utils", "thiserror", ] [[package]] name = "gix-merge" version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74bbcdcc52b70a32f0a151b024dff9d0fcf56ee48f00d9503e735af9d99ea881" dependencies = [ "bstr", "gix-command", "gix-diff", "gix-filter", "gix-fs", "gix-hash", "gix-imara-diff", "gix-index", "gix-object", "gix-path", "gix-quote", "gix-revision", "gix-revwalk", "gix-tempfile", "gix-trace", "gix-worktree", "nonempty", "thiserror", ] [[package]] name = "gix-negotiate" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "103d42bfade1b8a96ca5005933127bdad461ce588d92422b2c2daa3ff20d780c" dependencies = [ "bitflags", "gix-commitgraph", "gix-date", "gix-hash", "gix-object", "gix-revwalk", ] [[package]] name = "gix-object" version = "0.60.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a38075a95d7cc5df8afd38e72c617026c1456952207a4120a7f55a3fbf93b4d7" dependencies = [ "bstr", "gix-actor", "gix-date", "gix-features", "gix-hash", "gix-hashtable", "gix-utils", "gix-validate", "itoa", "smallvec", "thiserror", ] [[package]] name = "gix-odb" version = "0.80.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aeeda12a9663120418735ecdc1250d06eeab0be75700e47b3402a981331716ba" dependencies = [ "arc-swap", "gix-features", "gix-fs", "gix-hash", "gix-hashtable", "gix-object", "gix-pack", "gix-path", "gix-quote", "memmap2", "parking_lot", "tempfile", "thiserror", ] [[package]] name = "gix-pack" version = "0.70.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "daf02e6f5c8f07a069c9ea5245f40d9b14856ada4086091dc99941b49002b4fa" dependencies = [ "clru", "gix-chunk", "gix-error", "gix-features", "gix-hash", "gix-hashtable", "gix-object", "gix-path", "memmap2", "smallvec", "thiserror", ] [[package]] name = "gix-packetline" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "362246df440ee691699f0664cbf7006a6ece477db6734222be95e4198e5656e6" dependencies = [ "bstr", "faster-hex", "gix-trace", "thiserror", ] [[package]] name = "gix-path" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "671a6059e8a4c1b7f406e24716499cefa3926e060876fb1959ef225efeee346e" dependencies = [ "bstr", "gix-trace", "gix-validate", "thiserror", ] [[package]] name = "gix-pathspec" version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a84a4f083dd70fb49f4377e13afa6d90df2daaa1c705c49d6ff1331fc7e8855" dependencies = [ "bitflags", "bstr", "gix-attributes", "gix-config-value", "gix-glob", "gix-path", "thiserror", ] [[package]] name = "gix-protocol" version = "0.61.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4bee82db63ec635996b96efae71cf467c155fa3f34a556184373224a26c4fd" dependencies = [ "bstr", "gix-date", "gix-features", "gix-hash", "gix-ref", "gix-shallow", "gix-transport", "gix-utils", "maybe-async", "nonempty", "thiserror", ] [[package]] name = "gix-quote" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e97b73791a64bc0fa7dd2c5b3e551136115f97750b876ed1c952c7a7dbaf8be" dependencies = [ "bstr", "gix-error", "gix-utils", ] [[package]] name = "gix-ref" version = "0.63.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8ba9cc15f558b274c99349b83130f5ec83459660828fde9718bbbb43a726167" dependencies = [ "gix-actor", "gix-features", "gix-fs", "gix-hash", "gix-lock", "gix-object", "gix-path", "gix-tempfile", "gix-utils", "gix-validate", "memmap2", "thiserror", ] [[package]] name = "gix-refspec" version = "0.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61755b27d57edc8940a1b1593c8c61548ca8e4c02da1ed8d5bfeda9eb2a6b761" dependencies = [ "bstr", "gix-error", "gix-glob", "gix-hash", "gix-revision", "gix-validate", "smallvec", "thiserror", ] [[package]] name = "gix-revision" version = "0.45.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fb5288fac706d3ea3e4e2ba9ec38b78743b8c02f422e18cb342299cfd6ab7e8" dependencies = [ "bitflags", "bstr", "gix-commitgraph", "gix-date", "gix-error", "gix-hash", "gix-hashtable", "gix-object", "gix-revwalk", "gix-trace", "nonempty", ] [[package]] name = "gix-revwalk" version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "313813706b073a12ff7f9b2896bf3e6504cdac7cfbc97b1920114724705069f0" dependencies = [ "gix-commitgraph", "gix-date", "gix-error", "gix-hash", "gix-hashtable", "gix-object", "smallvec", "thiserror", ] [[package]] name = "gix-sec" version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f5a3a2d3e504a238136751e646a6c028252286a0ea64ea9974bf0498633407c6" dependencies = [ "bitflags", "gix-path", "libc", "windows-sys 0.61.2", ] [[package]] name = "gix-shallow" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29187305521bfacf4aefd284ab28dbfa9fb74abd39a5e63dd313b1baa5808c27" dependencies = [ "bstr", "gix-hash", "gix-lock", "nonempty", "thiserror", ] [[package]] name = "gix-status" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68c6d2a8c521ffa205fe7e268c82e6d1378ba37cd826ca10ab6129fdc29a4b65" dependencies = [ "bstr", "filetime", "gix-diff", "gix-dir", "gix-features", "gix-filter", "gix-fs", "gix-hash", "gix-index", "gix-object", "gix-path", "gix-pathspec", "gix-worktree", "portable-atomic", "thiserror", ] [[package]] name = "gix-submodule" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fd5fc8692890bd71a596e540fd4c364f8460eaa82c4eaaedebde6e1e3eb4d91" dependencies = [ "bstr", "gix-config", "gix-path", "gix-pathspec", "gix-refspec", "gix-url", "thiserror", ] [[package]] name = "gix-tempfile" version = "23.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "691ea1e31435c7e7d4d04705ec9d1c0d9482c46b2acf512bc723939d8f0af7fb" dependencies = [ "dashmap", "gix-fs", "libc", "parking_lot", "tempfile", ] [[package]] name = "gix-trace" version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f23569e55f2ffaf958617353b9734a7d52a7c19c439eeaa5e3efc217fd2270e" [[package]] name = "gix-transport" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffd6a5c676b92d4ead5f5a2b2935024415dec69edc997b6090ca9cac010a3018" dependencies = [ "bstr", "gix-command", "gix-features", "gix-packetline", "gix-quote", "gix-sec", "gix-url", "thiserror", ] [[package]] name = "gix-traverse" version = "0.57.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a14b7052c0786676c03e71fcfde7d7f0f8e8316e642b5cec6bb3998719b2ce5c" dependencies = [ "bitflags", "gix-commitgraph", "gix-date", "gix-hash", "gix-hashtable", "gix-object", "gix-revwalk", "smallvec", "thiserror", ] [[package]] name = "gix-url" version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35842d099e813f6f6bba529e88d4670572149c3df79b7a412952259887721ece" dependencies = [ "bstr", "gix-path", "percent-encoding", "thiserror", ] [[package]] name = "gix-utils" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e477b4f07a6e8da4ba791c53c858102959703c60d70f199932010d5b94adb2c" dependencies = [ "bstr", "fastrand", "unicode-normalization", ] [[package]] name = "gix-validate" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e26ac2602b43eadfdca0560b81d3341944162a3c9f64ccdeef8fc501ad80dad5" dependencies = [ "bstr", ] [[package]] name = "gix-worktree" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d69955eb5e2910832f88d041964b809eee01dadd579237e0b55efec58fd406fd" dependencies = [ "bstr", "gix-attributes", "gix-fs", "gix-glob", "gix-hash", "gix-ignore", "gix-index", "gix-object", "gix-path", "gix-validate", ] [[package]] name = "gix-worktree-state" version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a96dccbcf9e8fe0291c55f06e08da93ebb2e691c1311276f541eefcc6d70800" dependencies = [ "bstr", "gix-features", "gix-filter", "gix-fs", "gix-index", "gix-object", "gix-path", "gix-worktree", "io-close", "thiserror", ] [[package]] name = "gix-worktree-stream" version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8444b8ed4662e1a0c97f3eceda29630001a1bbb2632201e50312623e594213" dependencies = [ "gix-attributes", "gix-error", "gix-features", "gix-filter", "gix-fs", "gix-hash", "gix-object", "gix-path", "gix-traverse", "parking_lot", ] [[package]] name = "hash32" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" dependencies = [ "byteorder", ] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "foldhash 0.1.5", ] [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", "foldhash 0.2.0", ] [[package]] name = "hashbrown" version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ "hash32", "stable_deref_trait", ] [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" [[package]] name = "id-arena" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown 0.17.1", "serde", "serde_core", ] [[package]] name = "io-close" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cadcf447f06744f8ce713d2d6239bb5bde2c357a452397a9ed90c625da390bc" dependencies = [ "libc", "winapi", ] [[package]] name = "is-terminal" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itoa" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jiff" version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f00b5dbd620d61dfdcb6007c9c1f6054ebd75319f163d886a9055cec1155073d" dependencies = [ "jiff-static", "jiff-tzdb-platform", "log", "portable-atomic", "portable-atomic-util", "serde_core", "windows-sys 0.61.2", ] [[package]] name = "jiff-static" version = "0.2.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e000de030ff8022ea1da3f466fbb0f3a809f5e51ed31f6dd931c35181ad8e6d7" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "jiff-tzdb" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c900ef84826f1338a557697dc8fc601df9ca9af4ac137c7fb61d4c6f2dfd3076" [[package]] name = "jiff-tzdb-platform" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8" dependencies = [ "jiff-tzdb", ] [[package]] name = "kstring" version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "558bf9508a558512042d3095138b1f7b8fe90c5467d94f9f1da28b3731c5dbd1" dependencies = [ "static_assertions", ] [[package]] name = "leb128fmt" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libz-sys" version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc3a226e576f50782b3305c5ccf458698f92798987f551c6a02efe8276721e22" dependencies = [ "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "linux-raw-sys" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "lock_api" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ "scopeguard", ] [[package]] name = "log" version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "maybe-async" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "746873a384ad60adc5db74471dfaba74bd278afbdcfd81db93fafcdfc8b5ca0c" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "memchr" version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" [[package]] name = "memmap2" version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" dependencies = [ "adler2", "simd-adler32", ] [[package]] name = "nix" version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags", "cfg-if", "cfg_aliases", "libc", ] [[package]] name = "nonempty" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9737e026353e5cd0736f98eddae28665118eb6f6600902a7f50db585621fecb6" [[package]] name = "objc2" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ "objc2-encode", ] [[package]] name = "objc2-encode" version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "once_cell" version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "openssl-probe" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", "pkg-config", "vcpkg", ] [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", ] [[package]] name = "parking_lot_core" version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", "windows-link", ] [[package]] name = "percent-encoding" version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pkg-config" version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "portable-atomic" version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" [[package]] name = "portable-atomic-util" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" dependencies = [ "portable-atomic", ] [[package]] name = "prettyplease" version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" dependencies = [ "proc-macro2", "syn", ] [[package]] name = "proc-macro2" version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] [[package]] name = "prodash" version = "31.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "962200e2d7d551451297d9fdce85138374019ada198e30ea9ede38034e27604c" dependencies = [ "parking_lot", ] [[package]] name = "quote" version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "regex-automata" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys 0.61.2", ] [[package]] name = "rustversion" version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ "winapi-util", ] [[package]] name = "schannel" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "semver" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" dependencies = [ "serde_core", "serde_derive", ] [[package]] name = "serde_core" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "serde_json" version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", "serde", "serde_core", "zmij", ] [[package]] name = "sha1" version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", "digest", ] [[package]] name = "sha1-checked" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89f599ac0c323ebb1c6082821a54962b839832b03984598375bff3975b804423" dependencies = [ "digest", "sha1", ] [[package]] name = "shell-words" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6fe69c597f9c37bfeeeeeb33da3530379845f10be461a66d16d03eca2ded77" [[package]] name = "shlex" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "simd-adler32" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" dependencies = [ "libc", "windows-sys 0.61.2", ] [[package]] name = "stable_deref_trait" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] name = "stgit" version = "2.6.0" dependencies = [ "anstyle", "anyhow", "bstr", "bzip2-rs", "clap", "ctrlc", "curl", "encoding_rs", "flate2", "gix", "indexmap", "is-terminal", "jiff", "serde", "serde_json", "strsim", "tar", "tempfile", "termcolor", "thiserror", "winnow", ] [[package]] name = "strsim" version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tar" version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973" dependencies = [ "filetime", "libc", "xattr", ] [[package]] name = "tempfile" version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", "once_cell", "rustix", "windows-sys 0.61.2", ] [[package]] name = "termcolor" version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] [[package]] name = "terminal_size" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", "windows-sys 0.61.2", ] [[package]] name = "thiserror" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", "syn", ] [[package]] name = "tinyvec" version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] [[package]] name = "tinyvec_macros" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "typenum" version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-bom" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7eec5d1121208364f6793f7d2e222bf75a915c19557537745b195b253dd64217" [[package]] name = "unicode-ident" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" dependencies = [ "tinyvec", ] [[package]] name = "unicode-xid" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "utf8parse" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", ] [[package]] name = "wasip2" version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ "wit-bindgen 0.57.1", ] [[package]] name = "wasip3" version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ "wit-bindgen 0.51.0", ] [[package]] name = "wasm-encoder" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" dependencies = [ "leb128fmt", "wasmparser", ] [[package]] name = "wasm-metadata" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" dependencies = [ "anyhow", "indexmap", "wasm-encoder", "wasmparser", ] [[package]] name = "wasmparser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ "bitflags", "hashbrown 0.15.5", "indexmap", "semver", ] [[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ "windows-sys 0.61.2", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ "windows-targets", ] [[package]] name = "windows-sys" version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ "windows-link", ] [[package]] name = "windows-targets" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" dependencies = [ "wit-bindgen-rust-macro", ] [[package]] name = "wit-bindgen" version = "0.57.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "wit-bindgen-core" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" dependencies = [ "anyhow", "heck", "wit-parser", ] [[package]] name = "wit-bindgen-rust" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" dependencies = [ "anyhow", "heck", "indexmap", "prettyplease", "syn", "wasm-metadata", "wit-bindgen-core", "wit-component", ] [[package]] name = "wit-bindgen-rust-macro" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" dependencies = [ "anyhow", "prettyplease", "proc-macro2", "quote", "syn", "wit-bindgen-core", "wit-bindgen-rust", ] [[package]] name = "wit-component" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", "bitflags", "indexmap", "log", "serde", "serde_derive", "serde_json", "wasm-encoder", "wasm-metadata", "wasmparser", "wit-parser", ] [[package]] name = "wit-parser" version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" dependencies = [ "anyhow", "id-arena", "indexmap", "log", "semver", "serde", "serde_derive", "serde_json", "unicode-xid", "wasmparser", ] [[package]] name = "xattr" version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156" dependencies = [ "libc", "rustix", ] [[package]] name = "zlib-rs" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3be3d40e40a133f9c916ee3f9f4fa2d9d63435b5fbe1bfc6d9dae0aa0ada1513" [[package]] name = "zmij" version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" stgit-2.6.0/Cargo.toml000066400000000000000000000064001520252120500145730ustar00rootroot00000000000000[package] name = "stgit" version = "2.6.0" description = "Stack-based patch management for Git" edition = "2021" rust-version = "1.85" authors = [ "Catalin Marinas ", "Peter Grayson ", ] license = "GPL-2.0-only" homepage = "https://stacked-git.github.io/" repository = "https://github.com/stacked-git/stgit" keywords = ["git", "vcs", "cli", "utility"] categories = ["development-tools"] exclude = [ "/.github", "Documentation/", "/t", "/contrib/release", "/contrib/wix", ] [[bin]] bench = false path = "src/main.rs" name = "stg" [dependencies] anyhow = "1.0" anstyle = { version = "1.0", features = ["std"] } bstr = { version = "1.11", default-features = false, features = ["std"] } bzip2-rs = "0.1" clap = { version = "~4.6", default-features = false, features = [ "color", "help", "std", "string", "suggestions", "usage", "wrap_help", ] } ctrlc = "3.4" encoding_rs = "0.8" flate2 = "1" gix = { version = "0.83", default-features = false, features = [ "command", "revision", "sha1", ] } indexmap = "2.7" is-terminal = "0.4" jiff = "0.2.1" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" strsim = "0.11" tar = "0.4" tempfile = "3" termcolor = "1.4" thiserror = "~2.0" winnow = "1.0" curl = { version = "0.4", optional = true } [features] default = ["import-url"] import-url = ["dep:curl"] [profile.for-pkg] inherits = "release" lto = true strip = "none" [package.metadata.generate-rpm] assets = [ { source = "target/release/stg", dest = "/usr/bin/", mode = "755" }, { source = "README.md", dest = "/usr/share/doc/stgit/", mode = "644" }, { source = "COPYING", dest = "/usr/share/licenses/stgit/", mode = "644" }, { source = "Documentation/*.1", dest = "/usr/share/man/man1/", mode = "644", doc = true }, { source = "completion/stgit.zsh", dest = "/usr/share/zsh/site-functions/_stg", mode = "644" }, { source = "completion/stg.fish", dest = "/usr/share/fish/vendor_completions.d/", mode = "644" }, { source = "completion/stgit.bash", dest = "/usr/share/bash-completion/completions/stg", mode = "644" }, { source = "contrib/vim/ftdetect/stg.vim", dest = "/usr/share/vim/vimfiles/ftdetect/", mode = "644" }, { source = "contrib/vim/syntax/*.vim", dest = "/usr/share/vim/vimfiles/syntax/", mode = "644" }, ] requires = { git-core = "*", git-email = "*", vim-filesystem = "*" } [package.metadata.deb] maintainer = "Peter Grayson " section = "vcs" priority = "optional" depends = "git" recommends = "git-email" extended-description = "" assets = [ [ "target/release/stg", "usr/bin/", "755", ], [ "README.md", "usr/share/doc/stgit/", "644", ], [ "COPYING", "usr/share/doc/stgit/copyright", "644", ], [ "Documentation/*.1", "usr/share/man/man1/", "644", ], [ "completion/stgit.zsh", "usr/share/zsh/vendor-completions/_stg", "644", ], [ "completion/stg.fish", "usr/share/fish/vendor-completions.d/", "644", ], [ "completion/stgit.bash", "usr/share/bash-completion/completions/stg", "644", ], [ "contrib/vim/ftdetect/stg.vim", "usr/share/vim/addons/ftdetect/", "644", ], [ "contrib/vim/syntax/*.vim", "usr/share/vim/addons/syntax/", "644", ], ] stgit-2.6.0/Documentation/000077500000000000000000000000001520252120500154545ustar00rootroot00000000000000stgit-2.6.0/Documentation/.gitignore000066400000000000000000000001661520252120500174470ustar00rootroot00000000000000*.xml *.html *.[1-9] *.texi *.pdf stg-*.txt doc.dep txt-stamp command-list.txt manpage-base-url.xsl GIT-ASCIIDOCFLAGS stgit-2.6.0/Documentation/Makefile000066400000000000000000000172241520252120500171220ustar00rootroot00000000000000# Import tree-wide shared Makefile behavior and libraries # include ../shared.mak QUIET_SUBDIR0 = +$(MAKE) -C # space to separate -C and subdir QUIET_SUBDIR1 = ifneq ($(findstring w,$(MAKEFLAGS)),w) PRINT_DIR = --no-print-directory else # "make -w" NO_SUBDIR = : endif ifneq ($(findstring s,$(MAKEFLAGS)),s) ifndef V ## common QUIET_SUBDIR0 = +@subdir= QUIET_SUBDIR1 = ;$(NO_SUBDIR) echo ' ' SUBDIR $$subdir; \ $(MAKE) $(PRINT_DIR) -C $$subdir QUIET = @ QUIET_GEN = @echo ' ' GEN $@; QUIET_MKDIR_P_PARENT = @echo ' ' MKDIR -p $(@D); ## Used in "Documentation/Makefile" QUIET_ASCIIDOC = @echo ' ' ASCIIDOC $@; QUIET_XMLTO = @echo ' ' XMLTO $@; QUIET_DB2TEXI = @echo ' ' DB2TEXI $@; QUIET_MAKEINFO = @echo ' ' MAKEINFO $@; QUIET_DBLATEX = @echo ' ' DBLATEX $@; QUIET_XSLTPROC = @echo ' ' XSLTPROC $@; QUIET_GEN = @echo ' ' GEN $@; QUIET_STDERR = 2> /dev/null export V endif endif # Guard against environment variables MAN1_TXT = MAN5_TXT = MAN7_TXT = DOC_DEP_TXT = TECH_DOCS = ARTICLES = SP_ARTICLES = OBSOLETE_HTML = STG_PROFILE ?= release CARGO ?= cargo --locked CARGO_OFFLINE = $(CARGO) --offline CARGO_RUN = $(CARGO_OFFLINE) --quiet run --profile=$(STG_PROFILE) STG_COMMANDS_SRC = $(shell find ../src/cmd -name '*.rs') STG_COMMANDS_TXT = $(wildcard stg-*.txt) STGIT_VERSION := $(shell $(CARGO) metadata --format-version=1 --no-deps | \ grep -Eo '"version":"[^"]+"' | \ sed -Ee 's/"version":"([^"]+)"/\1/g') # STGIT_VERSION := $(shell $(CARGO_RUN) version --short | sed -e 's/stg //g') MAN1_TXT += stg.txt MAN1_TXT += $(STG_COMMANDS_TXT) DOC_DEP_TXT += $(wildcard *.txt) ifdef MAN_FILTER MAN_TXT = $(filter $(MAN_FILTER),$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)) else MAN_TXT = $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) MAN_FILTER = $(MAN_TXT) endif MAN_XML = $(patsubst %.txt,%.xml,$(MAN_TXT)) MAN_HTML = $(patsubst %.txt,%.html,$(MAN_TXT)) DOC_HTML=$(patsubst %.txt,%.html,$(MAN1_TXT)) ARTICLES_HTML += $(patsubst %,%.html,$(ARTICLES) $(SP_ARTICLES)) HTML_FILTER ?= $(ARTICLES_HTML) $(OBSOLETE_HTML) DOC_HTML = $(MAN_HTML) $(filter $(HTML_FILTER),$(ARTICLES_HTML) $(OBSOLETE_HTML)) DOC_MAN1 = $(patsubst %.txt,%.1,$(filter $(MAN_FILTER),$(MAN1_TXT))) DOC_MAN5 = $(patsubst %.txt,%.5,$(filter $(MAN_FILTER),$(MAN5_TXT))) DOC_MAN7 = $(patsubst %.txt,%.7,$(filter $(MAN_FILTER),$(MAN7_TXT))) prefix ?= $(HOME)/.local bindir ?= $(prefix)/bin htmldir ?= $(prefix)/share/doc/stgit infodir ?= $(prefix)/share/info pdfdir ?= $(prefix)/share/doc/stgit mandir ?= $(prefix)/share/man man1dir = $(mandir)/man1 man5dir = $(mandir)/man5 man7dir = $(mandir)/man7 # DESTDIR = ASCIIDOC = asciidoc ASCIIDOC_EXTRA = ASCIIDOC_HTML ?= xhtml11 ASCIIDOC_DOCBOOK = docbook ASCIIDOC_CONF = -f asciidoc.conf ASCIIDOC_COMMON = $(ASCIIDOC) $(ASCIIDOC_EXTRA) $(ASCIIDOC_CONF) \ -amanversion="$(STGIT_VERSION)" \ -amanmanual='StGit Manual' -amansource='StGit' ASCIIDOC_DEPS = asciidoc.conf GIT-ASCIIDOCFLAGS TXT_TO_HTML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_HTML) TXT_TO_XML = $(ASCIIDOC_COMMON) -b $(ASCIIDOC_DOCBOOK) MANPAGE_XSL = manpage-normal.xsl XMLTO = xmlto XMLTO_EXTRA = INSTALL ?= install RM ?= rm -f MAKEINFO = makeinfo INSTALL_INFO = install-info DOCBOOK2X_TEXI = docbook2x-texi DBLATEX = dblatex ASCIIDOC_DBLATEX_DIR = /etc/asciidoc/dblatex DBLATEX_COMMON = -p $(ASCIIDOC_DBLATEX_DIR)/asciidoc-dblatex.xsl -s $(ASCIIDOC_DBLATEX_DIR)/asciidoc-dblatex.sty ifndef PERL_PATH PERL_PATH = /usr/bin/perl endif ifndef NO_MAN_BOLD_LITERAL XMLTO_EXTRA += -m manpage-bold-literal.xsl endif # Newer DocBook stylesheet emits warning cruft in the output when # this is not set, and if set it shows an absolute link. Older # stylesheets simply ignore this parameter. # # Distros may want to use MAN_BASE_URL=file:///path/to/git/docs/ # or similar. ifndef MAN_BASE_URL MAN_BASE_URL = file://$(htmldir)/ endif XMLTO_EXTRA += -m manpage-base-url.xsl # If your target system uses GNU groff, it may try to render # apostrophes as a "pretty" apostrophe using unicode. This breaks # cut&paste, so you should set GNU_ROFF to force them to be ASCII # apostrophes. Unfortunately does not work with non-GNU roff. ifdef GNU_ROFF XMLTO_EXTRA += -m manpage-quote-apos.xsl endif ifdef USE_ASCIIDOCTOR ASCIIDOC = asciidoctor ASCIIDOC_CONF = ASCIIDOC_HTML = xhtml5 ASCIIDOC_DOCBOOK = docbook5 ASCIIDOC_EXTRA += -acompat-mode -atabsize=8 ASCIIDOC_EXTRA += -I. -rasciidoctor-extensions ASCIIDOC_EXTRA += -alitdd='&\#x2d;&\#x2d;' ASCIIDOC_DEPS = asciidoctor-extensions.rb GIT-ASCIIDOCFLAGS DBLATEX_COMMON = XMLTO_EXTRA += --skip-validation XMLTO_EXTRA += -x manpage.xsl endif SHELL_PATH ?= $(SHELL) # Shell quote; SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH)) # ' <-- help syntax highlighters back into good state all: html man html: $(DOC_HTML) man: man1 man5 man7 man1: $(DOC_MAN1) man5: $(DOC_MAN5) man7: $(DOC_MAN7) info: stgitman.info install: install-man install-man: man $(INSTALL) -d -m 755 $(DESTDIR)$(man1dir) $(INSTALL) -m 644 $(DOC_MAN1) $(DESTDIR)$(man1dir) install-info: info $(INSTALL) -d -m 755 $(DESTDIR)$(infodir) $(INSTALL) -m 644 stgitman.info $(DESTDIR)$(infodir) if test -r $(DESTDIR)$(infodir)/dir; then \ $(INSTALL_INFO) --info-dir=$(DESTDIR)$(infodir) stgitman.info ;\ else \ echo "No directory found in $(DESTDIR)$(infodir)" >&2 ; \ fi install-html: html $(INSTALL) -d -m 755 $(DESTDIR)$(htmldir) $(INSTALL) -m 644 $(DOC_HTML) $(DESTDIR)$(htmldir) $(DOC_HTML) $(DOC_MAN1): asciidoc.conf # # Determine "include::" file references in asciidoc files. # doc.dep : txt-stamp $(DOC_DEP_TXT) build-docdep.perl $(QUIET_GEN)$(PERL_PATH) ./build-docdep.perl >$@ $(QUIET_STDERR) ifneq ($(MAKECMDGOALS),clean) -include doc.dep endif TRACK_ASCIIDOCFLAGS = $(subst ','\'',$(ASCIIDOC_COMMON):$(ASCIIDOC_HTML):$(ASCIIDOC_DOCBOOK)) GIT-ASCIIDOCFLAGS: FORCE @FLAGS='$(TRACK_ASCIIDOCFLAGS)'; \ if test x"$$FLAGS" != x"`cat GIT-ASCIIDOCFLAGS 2>/dev/null`" ; then \ echo >&2 " * new asciidoc flags"; \ echo "$$FLAGS" >GIT-ASCIIDOCFLAGS; \ fi clean: $(RM) *.xml *.xml+ *.html *.html+ *.1 *.5 *.7 $(RM) *.texi *.texi+ *.texi++ stgitman.info $(RM) *.pdf $(RM) doc.dep $(RM) manpage-base-url.xsl $(RM) GIT-ASCIIDOCFLAGS $(RM) stg-*.txt $(RM) command-list.txt $(RM) txt-stamp $(MAN_HTML): %.html : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) -d manpage -o $@ $< $(OBSOLETE_HTML): %.html : %.txto $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_HTML) -o $@ $< manpage-base-url.xsl: manpage-base-url.xsl.in $(QUIET_GEN)sed "s|@@MAN_BASE_URL@@|$(MAN_BASE_URL)|" $< > $@ %.1 : %.xml manpage-base-url.xsl $(wildcard manpage*.xsl) $(QUIET_XMLTO)$(XMLTO) -m $(MANPAGE_XSL) $(XMLTO_EXTRA) man $< %.xml : %.txt $(ASCIIDOC_DEPS) $(QUIET_ASCIIDOC)$(TXT_TO_XML) -d manpage -o $@ $< stgitman.texi: $(MAN_XML) cat-texi.perl texi.xsl $(QUIET_DB2TEXI) \ ($(foreach xml,$(sort $(MAN_XML)),xsltproc -o $(xml)+ texi.xsl $(xml) && \ $(DOCBOOK2X_TEXI) --encoding=UTF-8 --to-stdout $(xml)+ && \ $(RM) $(xml)+ &&) true) > $@+ && \ $(PERL_PATH) cat-texi.perl $@ <$@+ >$@ && \ $(RM) $@+ stgitman.info: stgitman.texi $(QUIET_MAKEINFO)$(MAKEINFO) --no-split --no-validate $< $(patsubst %.txt,%.texi,$(MAN_TXT)): %.texi : %.xml $(QUIET_DB2TEXI)$(DOCBOOK2X_TEXI) --to-stdout $*.xml >$@ $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt $(QUIET_ASCIIDOC)$(TXT_TO_HTML) -a toc $*.txt print-man1: @for i in $(MAN1_TXT); do echo $$i; done .PHONY: FORCE $(STG_COMMANDS_TXT): txt-stamp stg.xml: stg.txt command-list.txt command-list.txt: $(STG_COMMANDS_SRC) $(QUIET_GEN)$(CARGO_RUN) completion list commands --style=asciidoc > $@ txt-stamp: $(STG_COMMANDS_SRC) $(QUIET)$(RM) txt-stamp-temp $(QUIET)touch txt-stamp-temp $(QUIET_GEN)$(CARGO_RUN) completion man $(QUIET)mv txt-stamp-temp $@ stgit-2.6.0/Documentation/asciidoc.conf000066400000000000000000000076051520252120500201110ustar00rootroot00000000000000## linkgit: macro # # Usage: linkgit:command[manpage-section] # # Note, {0} is the manpage section, while {target} is the command. # # Show Git link as: (
); if section is defined, else just show # the command. [macros] (?su)[\\]?(?Plinkgit):(?P\S*?)\[(?P.*?)\]= (?Plinkman):(?P\w+)\[(?P\d+)]= (?Plinkstgsub):(?P\w+)\[]= (?Plinkstg):(?P\w+)\[]= [attributes] asterisk=* plus=+ caret=^ startsb=[ endsb=] backslash=\ tilde=~ apostrophe=' backtick=` litdd=-- ifdef::backend-docbook[] [linkgit-inlinemacro] {0%{target}} {0#} {0#{target}{0}} {0#} endif::backend-docbook[] ifdef::backend-docbook[] ifndef::stgit-asciidoc-no-roff[] # "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. # v1.72 breaks with this because it replaces dots not in roff requests. [listingblock] {title} ifdef::doctype-manpage[] .ft C endif::doctype-manpage[] | ifdef::doctype-manpage[] .ft endif::doctype-manpage[] {title#} endif::stgit-asciidoc-no-roff[] ifdef::stgit-asciidoc-no-roff[] ifdef::doctype-manpage[] # The following two small workarounds insert a simple paragraph after screen [listingblock] {title} | {title#} [verseblock] {title} {title%} {title#} | {title#} {title%} endif::doctype-manpage[] endif::stgit-asciidoc-no-roff[] endif::backend-docbook[] ifdef::doctype-manpage[] ifdef::backend-docbook[] [header] template::[header-declarations] {mantitle} {manvolnum} {mansource} {manversion} {manmanual} {manname} {manpurpose} endif::backend-docbook[] endif::doctype-manpage[] ifdef::backend-xhtml11,backend-html5[] [attributes] git-relative-html-prefix= [linkgit-inlinemacro] # {target}{0?({0})} {target}{0?({0})} endif::backend-xhtml11,backend-html5[] ## linkman: macro # # Usage: linkman:command[manpage-section] # # Note, {0} is the manpage section, while {target} is the command. # # Show link as: (
); if section is defined, else just # show the command. ifdef::backend-docbook[] [linkman-inlinemacro] {0%{target}} {0#} {0#{target}{0}} {0#} endif::backend-docbook[] ifdef::backend-xhtml11,backend-html5[] [linkman-inlinemacro] {target}{0?({0})} endif::backend-xhtml11,backend-html5[] ## linkstg: macro # # Usage: linkstg:command[] # # Show StGit link as: stg-(1) in man pages, stg in # html. ifdef::backend-docbook[] [linkstg-inlinemacro] stg-{target}1 endif::backend-docbook[] ifdef::backend-xhtml11,backend-html5[] [linkstg-inlinemacro] stg {target} endif::backend-xhtml11,backend-html5[] ## linkstgsub: macro # # Usage: linkstgsub:command[] # # Show StGit link as: . ifdef::backend-docbook[] [linkstgsub-inlinemacro] {target} endif::backend-docbook[] ifdef::backend-xhtml11,backend-html5[] [linkstgsub-inlinemacro] {target} endif::backend-xhtml11,backend-html5[] stgit-2.6.0/Documentation/asciidoctor-extensions.rb000066400000000000000000000075441520252120500225130ustar00rootroot00000000000000require 'asciidoctor' require 'asciidoctor/extensions' module StGit module Documentation class LinkGitProcessor < Asciidoctor::Extensions::InlineMacroProcessor use_dsl named :chrome def process(parent, target, attrs) gitscm = 'https://git-scm.com/docs/' if parent.document.doctype == 'book' \ or parent.document.doctype == 'article' "" \ "#{target}(#{attrs[1]})" elsif parent.document.basebackend? 'html' %(#{target}(#{attrs[1]})) elsif parent.document.basebackend? 'docbook' "\n" \ "#{target}" \ "#{attrs[1]}\n" \ "" end end end class LinkManProcessor < Asciidoctor::Extensions::InlineMacroProcessor use_dsl named :chrome def process(parent, target, attrs) if parent.document.doctype == 'book' \ or parent.document.doctype == 'article' "#{target}(#{attrs[1]})" elsif parent.document.basebackend? 'html' %(#{target}(#{attrs[1]})) elsif parent.document.basebackend? 'docbook' "\n" \ "#{target}" \ "#{attrs[1]}\n" \ "" end end end class LinkStgProcessor < Asciidoctor::Extensions::InlineMacroProcessor use_dsl named :chrome def process(parent, target, attrs) if parent.document.doctype == 'book' \ or parent.document.doctype == 'article' "stg #{target}" elsif parent.document.basebackend? 'html' %(stg #{target}) elsif parent.document.basebackend? 'docbook' "\n" \ "stg-#{target}" \ "1\n" \ "" end end end class LinkStgSubProcessor < Asciidoctor::Extensions::InlineMacroProcessor use_dsl named :chrome def process(parent, target, attrs) if parent.document.doctype == 'book' \ or parent.document.doctype == 'article' "#{target}" elsif parent.document.basebackend? 'html' %(#{target}) elsif parent.document.basebackend? 'docbook' "\n" \ "stg-#{target}" \ "1\n" \ "" end end end class DocumentPostProcessor < Asciidoctor::Extensions::Postprocessor def process document, output if document.basebackend? 'docbook' mansource = document.attributes['mansource'] manversion = document.attributes['manversion'] manmanual = document.attributes['manmanual'] new_tags = "" \ "#{mansource}\n" \ "#{manversion}\n" \ "#{manmanual}\n" output = output.sub(/<\/refmeta>/, new_tags + "") end output end end end end Asciidoctor::Extensions.register do inline_macro StGit::Documentation::LinkGitProcessor, :linkgit inline_macro StGit::Documentation::LinkManProcessor, :linkman inline_macro StGit::Documentation::LinkStgProcessor, :linkstg inline_macro StGit::Documentation::LinkStgSubProcessor, :linkstgsub postprocessor StGit::Documentation::DocumentPostProcessor end stgit-2.6.0/Documentation/build-docdep.perl000077500000000000000000000020311520252120500206720ustar00rootroot00000000000000#!/usr/bin/perl my %include = (); my %included = (); for my $text (<*.txt>) { open I, '<', $text || die "cannot read: $text"; while () { if (/^include::/) { chomp; s/^include::\s*//; s/\[\]//; $include{$text}{$_} = 1; $included{$_} = 1; } } close I; } # Do we care about chained includes??? my $changed = 1; while ($changed) { $changed = 0; while (my ($text, $included) = each %include) { for my $i (keys %$included) { # $text has include::$i; if $i includes $j # $text indirectly includes $j. if (exists $include{$i}) { for my $j (keys %{$include{$i}}) { if (!exists $include{$text}{$j}) { $include{$text}{$j} = 1; $included{$j} = 1; $changed = 1; } } } } } } while (my ($text, $included) = each %include) { if (! exists $included{$text} && (my $base = $text) =~ s/\.txt$//) { my ($suffix) = '1'; if ($base eq 'git') { $suffix = '7'; # yuck... } print "$base.html $base.$suffix : ", join(" ", keys %$included), "\n"; } } stgit-2.6.0/Documentation/cat-texi.perl000077500000000000000000000014271520252120500200650ustar00rootroot00000000000000#!/usr/bin/perl -w use strict; use warnings; my @menu = (); my $output = $ARGV[0]; open my $tmp, '>', "$output.tmp"; while () { next if (/^\\input texinfo/../\@node Top/); next if (/^\@bye/ || /^\.ft/); if (s/^\@top (.*)/\@node $1,,,Top/) { push @menu, $1; } s/\(\@pxref\{\[(URLS|REMOTES)\]}\)//; s/\@anchor\{[^{}]*\}//g; print $tmp $_; } close $tmp; print '\input texinfo @setfilename stgitman.info @documentencoding UTF-8 @dircategory Development @direntry * StGit Man Pages: (stgitman). Manual pages for StGit @end direntry @node Top,,, (dir) @top StGit Manual Pages @documentlanguage en @menu '; for (@menu) { print "* ${_}::\n"; } print "\@end menu\n"; open $tmp, '<', "$output.tmp"; while (<$tmp>) { print; } close $tmp; print "\@bye\n"; unlink "$output.tmp"; stgit-2.6.0/Documentation/docbook-xsl.css000066400000000000000000000107151520252120500204160ustar00rootroot00000000000000/* CSS stylesheet for XHTML produced by DocBook XSL stylesheets. Tested with XSL stylesheets 1.61.2, 1.67.2 */ span.strong { font-weight: bold; } body blockquote { margin-top: .75em; line-height: 1.5; margin-bottom: .75em; } html body { margin: 1em 5% 1em 5%; line-height: 1.2; font-family: sans-serif; } body div { margin: 0; } h1, h2, h3, h4, h5, h6, div.toc p b, div.list-of-figures p b, div.list-of-tables p b, div.abstract p.title { color: #527bbd; font-family: tahoma, verdana, sans-serif; } div.toc p:first-child, div.list-of-figures p:first-child, div.list-of-tables p:first-child, div.example p.title { margin-bottom: 0.2em; } body h1 { margin: .0em 0 0 -4%; line-height: 1.3; border-bottom: 2px solid silver; } body h2 { margin: 0.5em 0 0 -4%; line-height: 1.3; border-bottom: 2px solid silver; } body h3 { margin: .8em 0 0 -3%; line-height: 1.3; } body h4 { margin: .8em 0 0 -3%; line-height: 1.3; } body h5 { margin: .8em 0 0 -2%; line-height: 1.3; } body h6 { margin: .8em 0 0 -1%; line-height: 1.3; } body hr { border: none; /* Broken on IE6 */ } div.footnotes hr { border: 1px solid silver; } div.navheader th, div.navheader td, div.navfooter td { font-family: sans-serif; font-size: 0.9em; font-weight: bold; color: #527bbd; } div.navheader img, div.navfooter img { border-style: none; } div.navheader a, div.navfooter a { font-weight: normal; } div.navfooter hr { border: 1px solid silver; } body td { line-height: 1.2 } body th { line-height: 1.2; } ol { line-height: 1.2; } ul, body dir, body menu { line-height: 1.2; } html { margin: 0; padding: 0; } body h1, body h2, body h3, body h4, body h5, body h6 { margin-left: 0 } body pre { margin: 0.5em 10% 0.5em 1em; line-height: 1.0; color: navy; } tt.literal, code.literal { color: navy; font-family: sans-serif; } code.literal:before { content: "'"; } code.literal:after { content: "'"; } em { font-style: italic; color: #064; } div.literallayout p { padding: 0em; margin: 0em; } div.literallayout { font-family: monospace; margin: 0em; color: navy; border: 1px solid silver; background: #f4f4f4; padding: 0.5em; } .programlisting, .screen { border: 1px solid silver; background: #f4f4f4; margin: 0.5em 10% 0.5em 0; padding: 0.5em 1em; } div.sidebar { background: #ffffee; margin: 1.0em 10% 0.5em 0; padding: 0.5em 1em; border: 1px solid silver; } div.sidebar * { padding: 0; } div.sidebar div { margin: 0; } div.sidebar p.title { font-family: sans-serif; margin-top: 0.5em; margin-bottom: 0.2em; } div.bibliomixed { margin: 0.5em 5% 0.5em 1em; } div.glossary dt { font-weight: bold; } div.glossary dd p { margin-top: 0.2em; } dl { margin: .8em 0; line-height: 1.2; } dt { margin-top: 0.5em; } dt span.term { font-style: normal; color: navy; } div.variablelist dd p { margin-top: 0; } div.itemizedlist li, div.orderedlist li { margin-left: -0.8em; margin-top: 0.5em; } ul, ol { list-style-position: outside; } div.sidebar ul, div.sidebar ol { margin-left: 2.8em; } div.itemizedlist p.title, div.orderedlist p.title, div.variablelist p.title { margin-bottom: -0.8em; } div.revhistory table { border-collapse: collapse; border: none; } div.revhistory th { border: none; color: #527bbd; font-family: tahoma, verdana, sans-serif; } div.revhistory td { border: 1px solid silver; } /* Keep TOC and index lines close together. */ div.toc dl, div.toc dt, div.list-of-figures dl, div.list-of-figures dt, div.list-of-tables dl, div.list-of-tables dt, div.indexdiv dl, div.indexdiv dt { line-height: normal; margin-top: 0; margin-bottom: 0; } /* Table styling does not work because of overriding attributes in generated HTML. */ div.table table, div.informaltable table { margin-left: 0; margin-right: 5%; margin-bottom: 0.8em; } div.informaltable table { margin-top: 0.4em } div.table thead, div.table tfoot, div.table tbody, div.informaltable thead, div.informaltable tfoot, div.informaltable tbody { /* No effect in IE6. */ border-top: 2px solid #527bbd; border-bottom: 2px solid #527bbd; } div.table thead, div.table tfoot, div.informaltable thead, div.informaltable tfoot { font-weight: bold; } div.mediaobject img { border: 1px solid silver; margin-bottom: 0.8em; } div.figure p.title, div.table p.title { margin-top: 1em; margin-bottom: 0.4em; } @media print { div.navheader, div.navfooter { display: none; } } stgit-2.6.0/Documentation/docbook.xsl000066400000000000000000000005521520252120500176260ustar00rootroot00000000000000 stgit-2.6.0/Documentation/fix-texi.perl000077500000000000000000000004651520252120500201050ustar00rootroot00000000000000#!/usr/bin/perl -w while (<>) { if (/^\@setfilename/) { $_ = "\@setfilename git.info\n"; } elsif (/^\@direntry/) { print '@dircategory Development @direntry * Git: (git). A fast distributed revision control system @end direntry '; } unless (/^\@direntry/../^\@end direntry/) { print; } } stgit-2.6.0/Documentation/manpage-base-url.xsl.in000066400000000000000000000005001520252120500217240ustar00rootroot00000000000000 @@MAN_BASE_URL@@ stgit-2.6.0/Documentation/manpage-bold-literal.xsl000066400000000000000000000010261520252120500221630ustar00rootroot00000000000000 \fB \fR stgit-2.6.0/Documentation/manpage-normal.xsl000066400000000000000000000015131520252120500211020ustar00rootroot00000000000000 .sp .br stgit-2.6.0/Documentation/manpage-quote-apos.xsl000066400000000000000000000011111520252120500217010ustar00rootroot00000000000000 ' \(aq stgit-2.6.0/Documentation/manpage.xsl000066400000000000000000000003041520252120500176110ustar00rootroot00000000000000 stgit-2.6.0/Documentation/stg.txt000066400000000000000000000375641520252120500170310ustar00rootroot00000000000000stg(1) ====== Yann Dirson NAME ---- stg - Manage stacks of patches using the Git content tracker SYNOPSIS -------- [verse] 'stg' [OPTIONS] [...] 'stg' [OPTIONS] \<-h|--help> 'stg' --version DESCRIPTION ----------- StGit (Stacked Git) is an application that provides a convenient way to maintain a 'patch stack' on top of a Git branch: * The topmost (most recent) commits of a branch are given names. Such a named commit is called a 'patch'. * After making changes to the worktree, you can incorporate the changes into an existing patch; this is called 'refreshing'. You may refresh any patch, not just the topmost one. * You can 'pop' a patch: temporarily putting it aside, so that the patch below it becomes the topmost patch. Later you may 'push' it onto the stack again. Pushing and popping can be used to reorder patches. * You can easily 'rebase' your patch stack on top of any other Git commit. (The 'base' of a patch stack is the most recent Git commit that is not an StGit patch.) For example, if you started making patches on top of someone else's branch, and that person publishes an updated branch, you can take all your patches and apply them on top of the updated branch. * As you would expect, changing what is below a patch can cause that patch to no longer apply cleanly -- this can occur when you reorder patches, rebase patches, or refresh a non-topmost patch. StGit uses Git's rename-aware three-way merge capability to automatically fix up what it can; if it still fails, it lets you manually resolve the conflict just like you would resolve a merge conflict in Git. * The patch stack is just some extra metadata attached to regular Git commits, so you can continue to use most Git tools along with StGit. Typical uses ~~~~~~~~~~~~ Tracking branch:: Tracking changes from a remote branch, while maintaining local modifications against that branch, possibly with the intent of sending some patches upstream. You can modify your patch stack as much as you want, and when your patches are finally accepted upstream, the permanent recorded Git history will contain just the final sequence of patches, and not the messy sequence of edits that produced them. + Commands of interest in this workflow are e.g. linkstgsub:rebase[] and linkstgsub:mail[]. Development branch:: Even if you have no "upstream" to send patches to, you can use StGit as a convenient way to modify the recent history of a Git branch. For example, instead of first committing change 'A', then change 'B', and then 'A2' to fix 'A' because it wasn't quite right, you could incorporate the fix directly into 'A'. This way of working results in a much more readable Git history than if you had immortalized every misstep you made on your way to the right solution. + Commands of interest in this workflow are e.g. linkstgsub:uncommit[], which can be used to move the patch stack base downwards -- i.e., turn Git commits into StGit patches after the fact -- and linkstgsub:commit[], its inverse. For more information, see the https://stacked-git.github.io/guides/tutorial[tutorial]. Specifying patches ~~~~~~~~~~~~~~~~~~ Most StGit commands have patch arguments. Patches in the stack may be specified in a variety of ways. A patch in the current branch may simply referred to by its name, or, alternatively, be located by a relative offset from the topmost patch (e.g. +{plus}3+), as an absolute index into the stack (e.g. +7+), or as an offset from the last visible patch (e.g. +{caret}1+). Some commands allow you to specify a patch in another branch of the repository; this is done by prefixing the patch name with the branch name and a colon (e.g. +otherbranch:thatpatch+). Commands that take multiple patch arguments may be supplied with patch ranges of the form +patch1..patchN+ as an alternative to specifying each patch individually. For example, `stg delete p0..p4` would be equivalent to `stg delete p0 p1 p2 p3 p4`. Patch ranges may be open on either or both ends. For example, `stg delete ..p2` would delete the first applied patch up to and including patch `p2`. Alternatively, `stg delete p2..` would delete patch `p2` up to and including the topmost applied patch. And `stg delete ..` would delete all applied patches. The complete syntax for locating patches follows: '', e.g. 'patch':: The name of a patch. '@':: Refers to the topmost applied patch, or the base of the stack if no patches are applied. '[]{tilde}[]', e.g. '{tilde}2', 'patch{tilde}', 'patch{tilde}3':: The th previous patch from the named patch. If is not supplied, '@' is implied. A single '{tilde}' represents the first previous patch. Multiple '{tilde}' may be specified, e.g. 'patch{tilde}{tilde}{tilde}' is the same as 'patch{tilde}3'. This is similar to git's revision syntax where '~[]' means the th ancestor commit from following first parents. '[]{plus}[]', e.g. '{plus}', '{plus}3', 'patch{plus}', 'patch{plus}3':: The th next patch from the named patch. If is not supplied, '@' is implied. A single '{plus}' represents the next patch in the series. Multiple '{plus}' may be specified, e.g. 'patch{plus}{plus}{plus}' is the same as 'patch{plus}3'. '-[]', e.g. '-3', '-':: References the th previously applied patch. This is similar to '~', except it is only valid without a patch name prefix. Note that certain commands with other options taking numeric values may require escaping '-' with '\-', e.g. '\-10'. '', e.g. '3':: The patch at absolute index in the stack. This is a zero-based index, so '0' refers to the bottommost patch in the stack. '{caret}[]', e.g. '{caret}', '{caret}3':: The patch at offset from the last visible patch in the stack. This is a zero-based offset, so '{caret}0' refers to the last visible patch in the stack, which is equivalent to just '{caret}'. Negative values of are allowed and refer to hidden patches which are after the last visible patch in the stack. '\{base}+[]', e.g. '\{base}+', '\{base}+3':: The patch at offset from the stack's base commit. Since the stack base is not a commit, a positive offset is required. Take note that numeric patch locations of the form '', '-', and '+', e.g. '3', '-3', or '+3' are also valid patch names. I.e. it is possible (but not recommended) to name a patch, for example, "-3". In the case where a patch name could also be interpreted as a numeric index or offset, the literal patch name will take precidence when resolving the patch location. Specifying commits ~~~~~~~~~~~~~~~~~~ Some StGit commands take Git commits as arguments. StGit accepts all revision specifications that Git does (see linkgit:gitrevisions[7]); and additionally, the patch specifiers from above. The usual Git modifiers, including $$^$$, are also allowed; e.g. +some-branch:a-patch^^+ refers to the grandparent of the commit that is patch +a-patch+ on branch +some-branch+. If you need to pass a given StGit reference to a Git command, linkstg:id[] will convert it to a Git commit id for you. OPTIONS ------- The following generic option flags are available. Additional options are available for (and documented with) the different subcommands. --version:: Print version information --help:: Print help information. -C:: Run as if stg was started in '' instead of the current working directory. When multiple `-C` options are given, each subsequent non-absolute `-C ` is interpreted relative to the preceding `-C `. + This option affects arguments that expect path names or path specs in that their interpretations of the path names would be made relative to the working directory caused by the `-C` option. --color :: Specify when to colorize the output. + `auto` (the default) enables colored output only when outputting to a terminal or TTY. The `NO_COLOR` environment variable is respected. + `always` and `never` unconditionlly enable/disable colored output, respectively. + `ansi` forces color to be output using ANSI escape sequences, even in a Windows console. STGIT COMMANDS -------------- We divide StGit commands in thematic groups, according to the primary type of object they create or change. ifdef::backend-docbook[] Here is a short description of each command. A more detailed description is available in individual command manpages. Those manpages are named 'stg-(1)'. endif::backend-docbook[] include::command-list.txt[] CONFIGURATION MECHANISM ----------------------- StGit uses the same configuration mechanism as Git. See linkgit:git-config[1] for more details. Variables ~~~~~~~~~ branch..stgit.autostash:: branch..stgit.fetchcmd:: branch..stgit.pull-policy:: branch..stgit.pullcmd:: branch..stgit.rebasecmd:: Branch-specific configuration values. These take precedence over the corresponding non-branch specific configuration values (see below). branch..stgit.parentbranch:: Specifies the parent branch of a branch with a StGit stack. This value is set by linkstg:branch[] when creating or cloning branches, and not typically set by the user. The parent branch is used by linkstg:pull[] when 'stgit.pull-policy' is either 'rebase' or 'fetch-rebase' to determine the target of the rebase. stgit.alias.*:: Command aliases for 'stg'. For example, after defining `stgit.alias.list = series -d`, running `stg list` is equivalent to `stg series -d`. Arguments are split by spaces and the usual shell quoting and escaping is supported. A quote pair or backslash may be used to quote them. + If the alias expansion is prefixed with an exclamation point (`!`), it will be treated as a shell command. For example, defining `stgit.alias.outgoing = !git log @{u}`, running `stg outgoing` is equivalent to running the shell command `git log @{u}`. Note that shell commands will be executed from the top-level directory of the working tree, which may not necessarily be the current directory. `GIT_PREFIX` is set as returned by running `git rev-parse --show-prefix` from the original current directory. See linkgit:git-rev-parse[1]. + Aliases that would hide existing StGit commands are ignored. stgit.autoimerge:: When set to 'true', if conflicts occur when pushing a patch, linkgit:git-mergetool[1] is automatically run to attempt to resolve the conflicts. stgit.autosign:: Automatically add signoff trailer to commit messages for new patches created with linkstg:new[] or lingstg:import[]. The value of this configuration variable will be used as the key of the trailer and therefore should be set to something like 'Signed-off-by'. stgit.autostash:: When running linkstg:rebase[], if any modified files are found in the working tree, a temporary stash is created with linkgit:git-stash[1] before the operation begins and is applied after the operation completes. stgit.diff-opts:: Options to pass-through to `git diff-tree` for linkstg:diff[], linkstg:export[], linkstg:patches[], and linkstg:show[]. Multiple space-separated options may be specified. See linkgit:git-diff-tree[1] for information about the various available options. stgit.edit.verbose:: When set to 'true', the patch's diff will be shown when interactively editing a patch description with, for example, linkstg:edit[]. stgit.editor:: Commands such as linkstg:edit[] and linkstg:new[] open an editor to edit the patch description and commit message. The editor set by this variable is launched when the 'GIT_EDITOR' environment variable is not set. This variable takes precedence over the `core.editor` configuration variable as well as the 'VISUAL' and 'EDITOR' environment variables. stgit.fetchcmd:: The command specified by this variable will be run by linkstg:pull[] to fetch from the remote repository when 'stgit.pull-policy' is 'fetch-rebase'. When not set, the default command is `git fetch`. stgit.gpgsign:: A boolean to specify whether StGit stack metadata commits should be GPG signed. + N.B. Set 'commit.gpgsign' to determine whether patch commits themselves are GPG signed. See linkgit:git-config[1] for more information about 'commit.gpgsign'. stgit.import.message-id:: When set to 'true', create 'Message-ID:' trailer in the patch description of patches imported from email using linkstg:import[]. stgit.keepoptimized:: When set to 'true', after pulling changes with linkstg:pull[], the repository's object database will be optimized by running linkgit:git-repack[1]. stgit.namelength:: An integer used to determine the maximum length, in characters, of automatically generated patch names. The default value is '30'. This option does not affect user-specified patch names. Setting to a value less than or equal to '0' will allow automatically generated patch names of unlimited length. + Automatically generated patch names are truncated at word boundaries less than or equal to the value of 'stgit.namelength'. As a result, patch names will typically not be truncated at exactly this number of characters. It is also possible for automatically generated patch names to be longer than this value if a work boundary cannot be found within this bound, or if additional characters need to be added to the patch name to make it unique. stgit.pick.expose-format:: Format of the commit message for patches picked using the '--expose' option with linkstg:pick[]. The value of this option is as may be specified to the '--pretty' option of linkgit:git-show[1]. The default is 'format:%B%n(imported from commit %H)'. stgit.pull-policy:: Policy used by linkstg:pull[] for pulling changes from a remote repository. Valid values include: + * `pull`, the default, uses linkgit:git-pull[1] or 'stgit.pullcmd', if set, to pull changes from the remote repository. * `rebase` uses linkgit:git-reset[1] or 'stgit.rebasecmd', if set, to rebase the patch stack before reapplying patches. * `fetch-rebase` first fetches commits from the remote repository using linkgit:git-fetch[1] or 'stgit.fetchcmd', if set, before performing the rebase as described above. stgit.pullcmd:: The command to be run by linkstg:pull[] to pull changes from the remote repository when 'stgit.pull-policy' is 'pull' (the default). The default value is `git pull`. stgit.push.allow-conflicts:: A boolean to specify whether linkstg:push[] and other commands that push patches will push patches that may result in merge conflicts. The default is 'true', which means that a patch with conflicts will be pushed and if the conflicts cannot be automatically resolved, the operation will stop and with the conflicts left to be resolved manually. + When set to 'false', a patch that would have merge conflicts will not be pushed, thus leaving the stack on the last patch that could be pushed without conflicts. + This configuration variable may be overridden on the command line with either `--conflicts[=allow]` or `--conflicts=disallow`. + N.B.: 'stgit.autoimerge' only has an affect when push conflicts are allowed. stgit.rebasecmd:: The command to be run by linkstg:pull[] to set the new stack base when 'stgit.pull-policy' is either 'rebase' or 'fetch-rebase'. The default is `git reset --hard`. stgit.refreshsubmodules:: A boolean to specify whether linkstg:refresh[] includes submodules in patch content. This value may be overridden by the '--submodules' or '--no-submodules' option to linkstg:refresh[]. By default, submodule content is not included in patch content. stgit.shortnr:: The number of patches listed by linkstg:series[] when the '-s'/'--short' option is specified. Defaults to '5'. TEMPLATES --------- A number of StGit commands make use of template files to provide useful default texts to be edited by the user. These +.tmpl+ template files are searched in the following directories: . +$GITDIR/+ (in practice, the +.git/+ directory in your repository) . +$XDG_CONFIG_HOME/stgit/templates/+ . +$HOME/.stgit/templates/+ stgit-2.6.0/Documentation/texi.xsl000066400000000000000000000014621520252120500171600ustar00rootroot00000000000000 refsect stgit-2.6.0/INSTALL.md000066400000000000000000000111031520252120500142670ustar00rootroot00000000000000Quick Install with Cargo ======================== A quick installation of the `stg` binary may be performed with `cargo`: ```shellsession $ cargo install --path=. ``` The above will install the `stg` executable to `~/.cargo/bin`, by default. The `--root` option, `CARGO_INSTALL_ROOT` environment variable, or `install.root` Cargo config value may be used to change where StGit is installed. The `--locked` option may be passed to `cargo install` to used the specific dependency versions from the `Cargo.lock` file, otherwise the latest semver-compatible versions of StGit's dependencies will be used. Full Installation ================= A more comprehensive installation of StGit, including man pages, shell completions, and html documentation may be achieved using various Makefile targets. To install the `stg` binary and man pages: ```shellsession $ make install install-man ``` By default, StGit is installed to the `$HOME/.local/{bin,share}` directories, as specified by the systemd file-hierarchy and XDG Base Directory specs. To install elsewhere, the `prefix` variable can be set: ```shellsession # make prefix=/usr/local install install-man ``` Shell completions may be installed with the `install-completion` target and html documentation with the `install-html` target. The `install-all` target installs the executable, man pages, html documentation, and shell completions. In addition to `prefix`, the `DESTDIR` variable may be used to re-root the installation to another directory. Using `DESTDIR` is most applicable when building StGit in the context of a packaging system (e.g. a Debian or RPM package). An example of a complete installation of StGit: ```shellsession $ make DESTDIR=/tmp/stgit-build prefix=/usr install-all ``` AsciiDoc and AsciiDoctor ------------------------ In addition to the Rust toolchain to build the `stg` executable, to build and install the documentation, AsciiDoc or AsciiDoctor along with `xmlto` is required. By default the documentation is built using `asciidoc`, but `asciidoctor` is also supported and may be enabled by using the `USE_ASCIIDOCTOR` make variable. ```shellsession $ make USE_ASCIIDOCTOR=1 install-man ``` Debian and RPM Packages ----------------------- The top-level Makefile has targets for building Debian and RPM packages. None of the distributions that use Debian and RPM packaging provide StGit 2.x (or 1.x) packages. The deb and rpm packages built from the StGit repository are meant to fill that gap. These StGit-provided packages do not necessarily conform to all of the packaging standards of those distributions. That said, an effort is made to properly install man pages, shell completions, and vim files in addition to the `stg` executable. In order to be maximally portable, the `stg` executable in these packages is statically linked using [musl][musl]. The following Makefile targets are available to build packages: - `packages`: build deb and rpm packages for all supported architectures - `debs`: build deb packages for all supported architectures - `rpms`: build rpm packages for all supported architectures - `deb-i686`: build `stgit_x.y.z_i386.deb` - `deb-x86_64`: build `stgit_x.y.z_amd64.deb` - `deb-aarch64`: build `stgit_x.y.z_arm64.deb` - `deb-riscv64`: build `stgit_x.y.z_riscv64.deb` - `rpm-i686`: build `stgit-x.y.z-w.i686.rpm` - `rpm-x86_64`: build `stgit-x.y.z-w.x86_64.rpm` - `rpm-aarch64`: build `stgit-x.y.z-w.aarch64.rpm` - `rpm-riscv64`: build `stgit-x.y.z-w.riscv64.rpm` The generated package files are output to `target/pkg/`. Rust Dependencies ================= To build these packages, rust needs to be setup for some additional targets: - aarch64-unknown-linux-musl - riscv64gc-unknown-linux-musl - i686-unknown-linux-musl - x86_64-unknown-linux-musl If using `rustup`, these targets can be added by with `rustup target add`. Cargo Dependencies ================== The `cargo-deb` and `cargo-generate-rpm` crates are used to generate the deb and rpm packages, respectively. These may be installed using `cargo install`. Linker Setup ============ When cross-compiling, e.g. when building aarch64 or riscv64 targets from an x86_64 host, the cross compiler linker needs to be installed and configured. On Arch Linux, install `aarch64-linux-gnu-gcc` and `riscv64-linux-gnu-gcc`. In Debian/Ubuntu environments, install the `gcc-aarch64-linux-gnu` and `gcc-riscv64-linux-gnu` packages. To configure, add the following to your `~/.cargo/config.toml` file: ```toml [target.aarch64-unknown-linux-musl] linker = "aarch64-linux-gnu-gcc" [target.riscv64gc-unknown-linux-musl] linker = "riscv64-linux-gnu-gcc" ``` [musl]: https://musl.libc.org/ stgit-2.6.0/Makefile000066400000000000000000000122751520252120500143120ustar00rootroot00000000000000prefix ?= $(HOME)/.local DESTDIR ?= DEFAULT_TEST_TARGET ?= test STG_PROVE_OPTS ?= STG_PROFILE ?= release CARGO ?= cargo --locked CARGO_OFFLINE = $(CARGO) --offline CARGO_RUN = $(CARGO_OFFLINE) --quiet run --profile=$(STG_PROFILE) RM ?= rm -f ifeq ($(STG_PROFILE),dev) TARGET_DIR = target/debug else TARGET_DIR = target/$(STG_PROFILE) endif export DESTDIR CARGO STG_PROFILE TEST_PATCHES ?= .. build: $(CARGO) build --profile=$(STG_PROFILE) all: build doc completion contrib completion: build $(MAKE) -C completion all contrib: $(MAKE) -C contrib all doc: build $(MAKE) -C Documentation all .PHONY: all build completion contrib doc install: install-bin install-all: install-bin install-completion install-contrib install-man install-html install-bin: build $(CARGO_OFFLINE) install --profile=$(STG_PROFILE) --path=. --root=$(DESTDIR)$(prefix) --no-track --force install-completion: build $(MAKE) -C completion install install-man: $(MAKE) -C Documentation install-man install-html: $(MAKE) -C Documentation install-html install-contrib: $(MAKE) -C contrib install .PHONY: install install-all install-bin install-completion install-contrib install-man install-html build-static-i686: $(CARGO) build --profile=for-pkg --target i686-unknown-linux-musl --no-default-features build-static-x86_64: $(CARGO) build --profile=for-pkg --target x86_64-unknown-linux-musl --no-default-features build-static-aarch64: $(CARGO) build --profile=for-pkg --target aarch64-unknown-linux-musl --no-default-features build-static-riscv64: $(CARGO) build --profile=for-pkg --target riscv64gc-unknown-linux-musl --no-default-features target/pkg: mkdir -p $@ deb-i686: completion doc target/pkg build-static-i686 $(CARGO_OFFLINE) deb --no-build --no-strip --output target/pkg/ --profile=for-pkg --target=i686-unknown-linux-musl deb-x86_64: completion doc target/pkg build-static-x86_64 $(CARGO_OFFLINE) deb --no-build --no-strip --output target/pkg/ --profile=for-pkg --target=x86_64-unknown-linux-musl deb-aarch64: completion doc target/pkg build-static-aarch64 $(CARGO_OFFLINE) deb --no-build --no-strip --output target/pkg/ --profile=for-pkg --target=aarch64-unknown-linux-musl deb-riscv64: completion doc target/pkg build-static-riscv64 $(CARGO_OFFLINE) deb --no-build --no-strip --output target/pkg/ --profile=for-pkg --target=riscv64gc-unknown-linux-musl debs: deb-i686 deb-x86_64 deb-aarch64 deb-riscv64 rpm-i686: completion doc target/pkg build-static-i686 $(CARGO_OFFLINE) generate-rpm --output target/pkg/ --profile=for-pkg --target=i686-unknown-linux-musl rpm-x86_64: completion doc target/pkg build-static-x86_64 $(CARGO_OFFLINE) generate-rpm --output target/pkg/ --profile=for-pkg --target=x86_64-unknown-linux-musl rpm-aarch64: completion doc target/pkg build-static-aarch64 $(CARGO_OFFLINE) generate-rpm --output target/pkg/ --profile=for-pkg --target=aarch64-unknown-linux-musl rpm-riscv64: completion doc target/pkg build-static-riscv64 $(CARGO_OFFLINE) generate-rpm --output target/pkg/ --profile=for-pkg --target=riscv64gc-unknown-linux-musl rpms: rpm-i686 rpm-x86_64 rpm-aarch64 rpm-riscv64 packages: debs rpms .PHONY: packages .PHONY: debs deb-i686 deb-x86_64 deb-aarch64 deb-riscv64 .PHONY: rpms rpm-i686 rpm-x86_64 rpm-aarch64 rpm-riscv64 .PHONY: build-static-i686 build-static-x86_64 build-static-aarch64 build-static-riscv64 lint: lint-format lint-clippy lint-api-doc lint-t unit-test lint-format: $(CARGO_OFFLINE) --quiet fmt --all --check lint-clippy: $(CARGO_OFFLINE) --quiet clippy -- --deny warnings lint-api-doc: $(CARGO_OFFLINE) --quiet doc --no-deps lint-t: $(MAKE) -C t test-lint unit-test: $(CARGO_OFFLINE) --quiet test .PHONY: lint lint-format lint-clippy lint-api-doc lint-t unit-test coverage: $(MAKE) coverage-test $(MAKE) coverage-html $(MAKE) coverage-report coverage-bin: RUSTFLAGS="-C instrument-coverage" $(CARGO) build --profile=$(STG_PROFILE) coverage-html: $(TARGET_DIR)/stg.profdata llvm-cov show \ --instr-profile=$< \ --object=$(TARGET_DIR)/stg \ -ignore-filename-regex='/.cargo/registry' \ -ignore-filename-regex='rustc/' \ -Xdemangler=rustfilt \ -format=html \ -output-dir=htmlcov coverage-report: $(TARGET_DIR)/stg.profdata llvm-cov report \ --instr-profile=$< \ --object=$(TARGET_DIR)/stg \ -ignore-filename-regex='/.cargo/registry' \ -ignore-filename-regex='rustc/' coverage-test: coverage-bin $(RM) $(TARGET_DIR)/stg.profdata $(MAKE) $(TARGET_DIR)/stg.profdata $(TARGET_DIR)/stg.profdata: -$(RM) -r $(TARGET_DIR)/.profraw -mkdir $(TARGET_DIR)/.profraw LLVM_PROFILE_FILE=$(CURDIR)/$(TARGET_DIR)/.profraw/stg-%m-%p.profraw \ $(MAKE) -C t all llvm-profdata merge -sparse -o $@ $(TARGET_DIR)/.profraw/*.profraw $(RM) -r $(TARGET_DIR)/.profraw .PHONY: coverage coverage-bin coverage-html coverage-report coverage-test format: $(CARGO_OFFLINE) fmt test: build $(MAKE) -C t all prove: build $(MAKE) -C t prove test-patches: for patch in $$($(CARGO_RUN) series --noprefix $(TEST_PATCHES)); do \ $(CARGO_RUN) goto $$patch && $(MAKE) test || break; \ done clean: $(MAKE) -C Documentation clean $(MAKE) -C t clean $(MAKE) -C completion clean $(MAKE) -C contrib clean $(RM) -r target $(RM) -r htmlcov .PHONY: format prove test test-patches clean stgit-2.6.0/README.md000066400000000000000000000074541520252120500141340ustar00rootroot00000000000000# Stacked Git Stacked Git, **StGit** for short, is an application for managing Git commits as a stack of patches. With a *patch stack* workflow, multiple patches can be developed concurrently and efficiently, with each patch focused on a single concern, resulting in both a clean Git commit history and improved productivity. For a complete introduction to StGit, see the [Stacked Git homepage](https://stacked-git.github.io). ## Getting started To get a feel for how StGit works, see this brief [example of StGit in action][example]. Or check out the [in-depth tutorial][tutorial]. [example]: https://stacked-git.github.io/guides/usage-example [tutorial]: https://stacked-git.github.io/guides/tutorial StGit also has a complete set of [man pages][man] describing the [`stg`][stg] command line tool and each of its subcommands. [man]: https://stacked-git.github.io/man [stg]: https://stacked-git.github.io/man/stg ## Installation See [`CHANGELOG.md`](CHANGELOG.md) to see what has changed in the latest StGit release. ### Dependencies StGit is implemented in Rust using a number of third-party, open source crates. StGit statically links with its pure-Rust dependencies, but dynamically links to libc and other non-Rust libraries when they are available at build-time. Dynamic link dependencies include these libraries along with their transient link dependencies: - libcurl (optional) StGit works within the context of a Git repository and performs many operations by running subordinate `git` commands. [Git](https://git-scm.com) 2.2.0 or newer is required. ### Package Repositories Recent versions of StGit are available in several package repositories such as [HomeBrew][pkg-homebrew] and [MacPorts][pkg-macports] for MacOS and for the [Arch][pkg-arch] and [Gentoo][pkg-gentoo] Linux distributions. StGit is also available via [crates.io][pkg-crate], [guix][pkg-guix], and [nix][pkg-nix]. More details about StGit packages availability for various operating systems can be [found on repology][repology]. [pkg-homebrew]: https://formulae.brew.sh/formula/stgit [pkg-macports]: https://ports.macports.org/port/stgit/ [pkg-arch]: https://aur.archlinux.org/packages/stgit [pkg-gentoo]: https://packages.gentoo.org/packages/dev-vcs/stgit [pkg-crate]: https://crates.io/crates/stgit [pkg-guix]: https://packages.guix.gnu.org/packages/stgit/ [pkg-nix]: https://search.nixos.org/packages?type=packages&query=stgit [repology]: https://repology.org/project/stgit/versions ### Prebuilt Packages Prebuilt deb, rpm, and msi packages are provided by the StGit project. Packages for the latest release may be found [here][latest]. Note that the Linux deb and rpm packages are unofficial. The upstream Debian and RedHat/Fedora projects currently only publish outdated versions of StGit (see [repology][repology]). These unofficial packages are meant to be a stop-gap until official StGit packages are provided by downstream distributions. The Linux deb and rpm packages are statically linked use [`musl`][musl] libc to maximize compatibility. They should hopefully work on a wide range of deb and rpm based distributions. [musl]: https://musl.libc.org/ ### Source Installation StGit may also be installed from source. Download the [latest release][latest] or clone from the [StGit repository on GitHub][repo]. [latest]: https://github.com/stacked-git/stgit/releases/latest [repo]: https://github.com/stacked-git/stgit To install the `stg` executable from source, choose a `prefix` and run: ```shellsession $ make prefix=$HOME/.local install ``` For more information about installation, see [`INSTALL.md`](INSTALL.md). ## Contributing See [`CONTRIBUTING.md`](CONTRIBUTING.md) for a full guide to contributing to StGit. ## Maintainers StGit is maintained by Catalin Marinas and Peter Grayson. For a complete list of StGit's authors, see [`AUTHORS.md`](AUTHORS.md). stgit-2.6.0/TODO000066400000000000000000000002421520252120500133310ustar00rootroot00000000000000- Patch dependency tracking - Multiple heads in a patch - useful for forking a patch, synchronising with other patches (diff format or in other repositories) stgit-2.6.0/build.rs000066400000000000000000000070401520252120500143110ustar00rootroot00000000000000fn main() { let git_output = std::process::Command::new("git") .args(["rev-parse", "--git-dir"]) .output() .ok(); let git_dir = git_output.as_ref().and_then(|output| { std::str::from_utf8(&output.stdout) .ok() .and_then(|s| s.strip_suffix('\n').or_else(|| s.strip_suffix("\r\n"))) }); // Tell cargo to rebuild if the head or any relevant refs change. if let Some(git_dir) = git_dir { let git_path = std::path::Path::new(git_dir); let refs_path = git_path.join("refs"); if git_path.join("HEAD").exists() { println!("cargo:rerun-if-changed={git_dir}/HEAD"); } if git_path.join("packed-refs").exists() { println!("cargo:rerun-if-changed={git_dir}/packed-refs"); } if refs_path.join("heads").exists() { println!("cargo:rerun-if-changed={git_dir}/refs/heads"); } if refs_path.join("tags").exists() { println!("cargo:rerun-if-changed={git_dir}/refs/tags"); } } let git_output = std::process::Command::new("git") .args([ "describe", "--match=v*", "--abbrev=9", "--long", "--dirty=*", ]) .output() .ok(); let git_hash = git_output .as_ref() .and_then(|output| std::str::from_utf8(&output.stdout).ok().map(str::trim)) // E.g. "v2.0.0-beta.2-7-g12ab34cd56*" // ttttttttttttt N hhhhhhhhhhhD // t => last matching annotated tag // N => distance (in commits) from tag // h => git commit id (hash) // D => work tree dirty flag // // N.B. Since the tag may have '-' characters, the description string is parsed // from right to left. .and_then(|desc| { desc.rsplit_once('-').and_then(|(tag_and_distance, hash)| { let hash = hash .strip_prefix('g') .expect("git hash component starts with 'g'"); let dirty = hash.ends_with('*'); tag_and_distance .rsplit_once('-') .and_then(|(tag, distance_from_tag)| { let tag = tag .strip_prefix('v') .expect("last annotated tag starts with 'v'"); let distance_from_tag = distance_from_tag .parse::() .expect("distance from tag is usize"); let cargo_pkg_version = env!("CARGO_PKG_VERSION"); if tag != cargo_pkg_version { println!( "cargo:warning=\ version from Cargo.toml, \"{cargo_pkg_version}\", \ does not match last annotated tag \"{tag}\"" ); } if tag == cargo_pkg_version && distance_from_tag == 0 && !dirty { // Do not use/display hash when the cargo version exactly // matches the latest annotated tag. None } else { Some(hash) } }) }) }); // Make the current git hash available to the build. if let Some(git_hash) = git_hash { println!("cargo:rustc-env=STGIT_BUILD_GIT_HASH={git_hash}"); } } stgit-2.6.0/completion/000077500000000000000000000000001520252120500150145ustar00rootroot00000000000000stgit-2.6.0/completion/Makefile000066400000000000000000000017461520252120500164640ustar00rootroot00000000000000STG_PROFILE ?= release CARGO ?= cargo --locked CARGO_OFFLINE = $(CARGO) --offline CARGO_RUN = $(CARGO_OFFLINE) --quiet run --profile=$(STG_PROFILE) INSTALL ?= install prefix ?= $(HOME)/.local bashdir ?= $(prefix)/share/bash-completion/completions fishdir ?= $(prefix)/share/fish/vendor_completions.d zshdir ?= $(prefix)/share/zsh/site-functions all: stgit.bash stg.fish .PHONY: all install: install-bash install-fish install-zsh install-bash: stgit.bash $(INSTALL) -d -m 755 $(DESTDIR)$(bashdir) $(INSTALL) -m 644 stgit.bash $(DESTDIR)$(bashdir)/stg install-fish: stg.fish $(INSTALL) -d -m 755 $(DESTDIR)$(fishdir) $(INSTALL) -m 644 stg.fish $(DESTDIR)$(fishdir)/stg.fish install-zsh: $(INSTALL) -d -m 755 $(DESTDIR)$(zshdir) $(INSTALL) -m 644 stgit.zsh $(DESTDIR)$(zshdir)/_stg .PHONY: install install-bash install-fish install-zsh stgit.bash: $(CARGO_RUN) completion bash > $@ stg.fish: $(CARGO_RUN) completion fish > $@ clean: rm -f stgit.bash rm -f stg.fish .PHONY: clean stgit-2.6.0/completion/stgit.zsh000066400000000000000000001604071520252120500167040ustar00rootroot00000000000000#compdef stg # This script implements zsh completions for StGit (stg). # # To use these completions, copy to a directory in $fpath as _stgit. # For example: # # $ mkdir ~/.zsh.d # $ stg completion zsh >~/.zsh.d/_stgit # $ $EDITOR ~/.zshrc # # fpath=("$HOME/.zsh.d" $fpath) # autoload -U compinit # _stg-branch() { local -a subcmd_args local curcontext="$curcontext" state line integer ret=1 __stg_add_args_help __stg_add_args_color subcmd_args+=( ': :->command' '*:: :->option-or-argument' ) _arguments -C $subcmd_args && ret=0 case $state in (command) declare -a commands switch_options commands=( {-l,--list}':list branches' {-c,--create}':create and switch to new branch' {-C,--clone}':clone current branch to new branch' {-r,--rename}':rename existing branch' {-p,--protect}':prevent stg from modifying branch' {-u,--unprotect}':allow stg to modify branch' {-D,--delete}':delete branch' '--cleanup:cleanup stg metadata for branch' {-d,--describe}':set branch description' ) switch_options=( '--merge:merge worktree changes into other branch' ) _alternative \ 'command: : _describe -t commands command commands' \ 'switch-option: : _describe -t switch-options switch-option switch_options' \ 'branch: : __stg_git_branch_names' && ret=0 ;; (option-or-argument) curcontext=${curcontext%:*}-$line[1] case $line[1] in (--cleanup) _call_function ret _stg-branch-cleanup ;; (-C|--clone) _call_function ret _stg-branch-clone ;; (-c|--create) _call_function ret _stg-branch-create ;; (-D|--delete) _call_function ret _stg-branch-delete ;; (-d|--describe|--description) _call_function ret _stg-branch-describe ;; (-l|--list) _call_function ret _stg-branch-list ;; (-p|--protect) _call_function ret _stg-branch-protect ;; (-r|--rename) _call_function ret _stg-branch-rename ;; (-u|--unprotect) _call_function ret _stg-branch-unprotect ;; # Options and arguments for the default command (switch branch). (--merge) _call_function ret _stg-branch-switch has-merge ;; (*) _call_function ret _stg-branch-switch has-branch ;; esac ;; esac return ret } _stg-branch-switch() { local -a subcmd_args __stg_add_args_help __stg_add_args_color if [ "$1" != "has-merge" ]; then subcmd_args+=('--merge[merge worktree changes into other branch]') fi if [ "$1" != "has-branch" ]; then subcmd_args+=(':branch:__stg_git_branch_names') fi _arguments -S $subcmd_args } _stg-branch-cleanup() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '--force[force cleanup when series is non-empty]' ':stgit branch:__stg_stgit_branch_names' ) _arguments -S $subcmd_args } _stg-branch-clone() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments $subcmd_args ':new-branch:' } _stg-branch-create() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments -s -S $subcmd_args ':new-branch:' ':committish:' } _stg-branch-delete() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '--force[force cleanup when series is non-empty]' ':branch:__stg_git_branch_names' ) _arguments -s -S $subcmd_args } _stg-branch-describe() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments -s -S $subcmd_args ':description:' ':branch:__stg_git_branch_names' } _stg-branch-list() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments $subcmd_args } _stg-branch-protect() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments $subcmd_args ':branch:__stg_stgit_branch_names' } _stg-branch-rename() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( ':old or new branch name:__stg_git_branch_names' '::new branch name:__stg_git_branch_names' ) _arguments $subcmd_args } _stg-branch-unprotect() { local -a subcmd_args __stg_add_args_help __stg_add_args_color _arguments $subcmd_args ':branch:__stg_stgit_branch_names' } _stg-clean() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '(-A --applied)'{-A,--applied}'[delete empty applied patches]' '(-U --unapplied)'{-U,--unapplied}'[delete empty unapplied patches]' ) _arguments -s -S $subcmd_args } _stg-commit() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '--allow-empty[allow committing empty patches]' - group-all '(-a --all)'{-a,--all}'[commit all applied patches]' - group-number '(-n --number)'{-n+,--number=}'[commit specified number of patches]:number' - group-patches '*:applied patches:__stg_dedup_inside_arguments __stg_patchrange --suggest-range --applied' ) _arguments -s -S $subcmd_args } _stg-completion() { local -a subcmd_args local curcontext="$curcontext" state line __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( bash:'generate bash completion script' fish:'generate fish shell completion script' zsh:'generate zsh completion script' list:'list StGit command information' man:'generate asciidoc man pages' help:'show help for given subcommand' ) _describe -t commands 'completion command' command_list ;; (option-or-argument) curcontext=${curcontext%:*:*}:stg-completion-$words[1] if ! _call_function ret _stg-completion-$words[1]; then _message "unknown subcommand: $words[1]" fi esac return ret } _stg-completion-bash() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' ) _arguments -s -S $subcmd_args } _stg-completion-fish() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' ) _arguments -s -S $subcmd_args } _stg-completion-zsh() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' ) _arguments -s -S $subcmd_args } _stg-completion-man() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_directories' ) _arguments -s -S $subcmd_args } _stg-completion-help() { local -a subcmd_args local curcontext="$curcontext" state line subcmd_args+=( '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( bash:'generate bash completion script' fish:'generate fish shell completion script' zsh:'generate zsh completion script' list:'list StGit command information' help:'show help for given subcommand' ) _describe -t commands 'completion command' command_list ;; (option-or-argument) curcontext=${curcontext%:*:*}:stg-completion-$words[1]-help _call_function ret _stg-completion-$words[1]-help ;; esac return ret } _stg-completion-list() { local -a subcmd_args local curcontext="$curcontext" state line __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' '--style=-[output format style]:style:(name-only fish zsh asciidoc)' '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( aliases:'list aliases' commands:'list StGit commands' commands-and-aliases:'list StGit commands and aliases' help:'show help for given subcommand' ) _describe -t commands 'completion command' command_list ;; (option-or-argument) curcontext=${curcontext%:*:*}:stg-completion-list-$words[1] if ! _call_function ret _stg-completion-list-$words[1]; then _message "unknown subcommand: $words[1]" fi ;; esac return ret } _stg-completion-list-help() { local -a subcmd_args local curcontext="$curcontext" state line subcmd_args+=( '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( aliases:'list aliases' commands:'list StGit commands' commands-and-aliases:'list StGit commands and aliases' help:'show help for given subcommand' ) _describe -t commands 'completion command' command_list ;; (option-or-argument) ;; esac return ret } _stg-completion-list-aliases() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' '--style=-[output format style]:style:(name-only fish zsh asciidoc)' '--show-expansion[show alias expansion]' ) _arguments -s -S $subcmd_args } _stg-completion-list-commands() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' '--style=-[output format style]:style:(name-only fish zsh asciidoc)' ) _arguments -s -S $subcmd_args } _stg-completion-list-commands-and-aliases() { local -a subcmd_args __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-o --output)'{-o,--output=}'[output to path]: :_files' '--style=-[output format style]:style:(name-only fish zsh asciidoc)' ) _arguments -s -S $subcmd_args } _stg-delete() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch __stg_add_args_push_conflicts subcmd_args+=( '--spill[spill patch contents to worktree and index]' - group-ahu '(-A --applied)'{-A,--applied}'[delete applied patches]' '(-H --hidden)'{-H,--hidden}'[delete hidden patches]' '(-U --unapplied)'{-U,--unapplied}'[delete unapplied patches]' - group-all '--all[delete all patches]' - group-top '(-t --top)'{-t,--top}'[delete top patch]' - group-patchnames '*:patches:__stg_dedup_inside_arguments __stg_patchrange --all' ) _arguments -s -S $subcmd_args } _stg-diff() { local -a subcmd_args __stg_add_args_help __stg_add_args_diffopt subcmd_args+=( '(-r --range)'{-r,--range=}'[show diff between revisions]: :__stg_patchrange --suggest-range --all' '(-s --stat)'{-s,--stat}'[show stat instead of diff]' '*:files:__stg_changed_files' ) _arguments -s -S $subcmd_args } _stg-edit() { local -a subcmd_args __stg_add_args_help __stg_add_args_author __stg_add_args_edit __stg_add_args_committer_date_is_author_date __stg_add_args_hook __stg_add_args_savetemplate __stg_add_args_trailers subcmd_args+=( '(-d --diff)'{-d,--diff}'[edit patch diff]' '(-t --set-tree)'{-t,--set-tree=}'[set git tree of patch]:treeish' ':patch:__stg_patch --all' ) __stg_add_args_message _arguments -s -S $subcmd_args } _stg-email() { local -a subcmd_args local curcontext="$curcontext" state line __stg_add_args_help __stg_add_args_color subcmd_args+=( '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( format:'format patches as email files' send:'send patches as emails' help:'show help for given subcommand' ) _describe -t commands 'email command' command_list ;; (option-or-argument) curcontext=${curcontext%:*:*}:stg-email-$words[1] if ! _call_function ret _stg-email-$words[1]; then _message "unknown subcommand: $words[1]" fi ;; esac return ret } _stg-email-format() { local curcontext=$curcontext state line ret=1 local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch subcmd_args+=( '*'{-G+,--git-opt=}'[extra option for git-format-patch]:opt:__stg_git_format_patch_opts' '(-o --output-directory)'{-o+,--output-directory=}'[store resulting files in given directory]: :_directories' '(-n --numbered -N --no-numbered -k --keep-subject)'{-n,--numbered}'[name output in \[PATCH n/m\] format]' '(-n --numbered -N --no-numbered -k --keep-subject)'{-N,--no-numbered}'[name output in \[PATCH\] format]' '--start-number=[start numbering patches at given number]: :_numbers -l 1 "patch number"' '--numbered-files[use only number for file name]' '(-n --numbered -N --no-numbered -k --keep-subject --rfc --subject-prefix)'{-k,--keep-subject}"[don't strip/add \[PATCH\] from the first line of the commit message]" '(-s --signoff)'{-s,--signoff}'[add Signed-off-by: trailer to the commit message]' '( --inline)--attach[create attachments instead of inlining patches]' '(--attach )--inline[inline patches]' '(--thread )--no-thread[do not thread messages]' '( --no-thread)--thread=-[make the second and subsequent mails refer to the first]::style:((shallow\:"all refer to the first" deep\:"each refers to the previous"))' '--in-reply-to=[make the first mail a reply to the given message]:message id' '(-v --reroll-count)'{-v+,--reroll-count=}'[mark the series as the -th iteration of the topic]: :_numbers iteration' '(-k --keep-subject --subject-prefix)--rfc[use \[RFC PATCH\] instead of \[PATCH\]]' '(-k --keep-subject --rfc)--subject-prefix=[use the given prefix instead of \[PATCH\]]:prefix' '(--no-to)*--to=[add To: header to email headers]: :_email_addresses' '--no-to[discard all To: headers added so far]' '(--no-cc)*--cc=[add Cc: header to email headers]: :_email_addresses' '--no-cc[discard all Cc: headers added so far]' '*--add-header=[add an arbitrary header to email headers]:header' \ '--cover-letter[generate a cover letter]' '( --no-signature --signature-file)--signature=[add a signature]:signature' '(--signature --signature-file)--no-signature[do not add a signature]' '(--signature --no-signature )--signature-file=[use contents of file as signature]: :_files' '--base=[add prerequisite tree info to the patch series]:prereq commit:__stg_revisions' '--suffix=[use the given suffix for filenames]:filename suffix' '(-q --quiet)'{-q,--quiet}'[suppress the output of the names of generated files]' '--no-binary[do not output contents of changes in binary files, only note that they differ]' '--zero-commit[output all-zero hash in From header]' '--progress[show progress while generating patches]' '--interdiff=[insert interdiff against previous patch series in cover letter or single patch]:reference to tip of previous series:__stg_revisions' '--range-diff=[insert range-diff against previous patch series in cover letter or single patch]:reference to tip of previous series:__stg_revisions' '--creation-factor=[for range-diff, specify weighting for creation]:weighting (percent)' + '(sources)' '(-a --all)'{-a,--all}'[format all applied patches]' ': :->patch-or-patch-range' ) _arguments -s -S $subcmd_args && ret=0 case $state in (patch-or-patch-range) __stg_patchrange --suggest-range && ret=0 ;; esac return ret } _stg-email-send() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch subcmd_args+=( '*'{-G+,--git-opt=}'[extra option for git-send-email]:opt:__stg_git_send_email_opts' '--from=[specify sender]:email address:_email_addresses' '--to=[specify the primary recipient of the emails]: :_email_addresses' '--cc=[starting Cc: value for each email]: :_email_addresses' '--bcc=[Bcc: value for each email]: :_email_addresses' '--subject=[specify the initial subject of the email thread]:subject' '--reply-to=[specify Reply-To address]:email address:_email_addresses' '--in-reply-to=[specify contents of first In-Reply-To header]:message-id' '--compose[edit introductory message for patch series]' '--annotate[review each patch in an editor]' '--identity=[specify configuration identity]: :__stg_email_send_identities' '--no-thread[do not set In-Reply-To: and References: headers]' '--confirm[specify type of confirmation required before sending]: :(( always\:"always confirm before sending" never\:"never confirm before sending" cc\:"confirm before sending to automatically added Cc-addresses" compose\:"confirm before sending first message when using --compose" auto\:"same as cc together with compose" ))' '--quiet[be less verbose]' '--dry-run[do everything except actually sending the emails]' + '(sources)' '(-a --all)'{-a,--all}'[send all applied patches]' '(- *)--dump-aliases[dump configured aliases and exit]' '*: : _alternative -O expl "files:file:_files" "patchrange::__stg_patchrange --suggest-range"' ) _arguments -s -S $subcmd_args } _stg-email-help() { local -a subcmd_args local curcontext="$curcontext" state line subcmd_args+=( '(-): :->command' '(-)*:: :->option-or-argument' ) integer ret=1 _arguments -s -S $subcmd_args && ret=0 case $state in (command) local -a command_list=( format:'format patches as email files' send:'send patches as emails' help:'show help for given subcommand' ) _describe -t commands 'email command' command_list ;; (option-or-argument) curcontext=${curcontext%:*:*}:stg-email-$words[1]-help _call_function ret _stg-email-$words[1]-help ;; esac return ret } _stg-export() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch __stg_add_args_diffopt subcmd_args+=( '(-d --dir)'{-d,--dir}'[export patches to directory]: :_directories' '(-n --numbered)'{-n,--numbered}'[prefix patch names with order numbers]' '(-s --stdout)'{-s,--stdout}'[dump patches to standard output]' '(-t --template)'{-t,--template=}'[use template file]: :_files' '*:patches:__stg_dedup_inside_arguments __stg_patchrange' + '(suffix)' '(-e --extension)'{-e,--extension=}'[extension to append to patch names]:extension' '(-p --patch)'{-p,--patch}'[append .patch to patch names]' ) _arguments -s -S $subcmd_args } _stg-files() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '--bare[bare file names]' '(-s --stat)'{-s,--stat}'[show diff stat]' ':patches:__stg_patch --all' ) _arguments -s -S $subcmd_args } _stg-float() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_keep __stg_add_args_committer_date_is_author_date subcmd_args+=( '--noapply[Reorder patches by floating without applying]' '(-S --series)'{-S,--series=}'[arrange according to series file]: :_files' '*:patches:__stg_dedup_inside_arguments __stg_patchrange --all' ) _arguments -s -S $subcmd_args } _stg-fold() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '(-b --base)'{-b,--base=}'[apply on base commit instead of HEAD]:commit' '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num' '-C=[ensure N lines of surrounding context for each change]:num' '--reject[leave rejected hunks in .rej files]' ':file:_files' ) _arguments -s -S $subcmd_args } _stg-goto() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_keep __stg_add_args_merged __stg_add_args_committer_date_is_author_date __stg_add_args_push_conflicts subcmd_args+=( ':patches:__stg_patch --all' ) _arguments -s -S $subcmd_args } _stg-help() { _arguments -s ':commands:__stg_subcommands' } _stg-hide() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch subcmd_args+=( '*:patches:__stg_dedup_inside_arguments __stg_patchrange' ) _arguments -s -S $subcmd_args } _stg-id() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch subcmd_args+=( ':references:__stg_patch --all' ) _arguments -s -S $subcmd_args } _stg-import() { local -a subcmd_args __stg_add_args_help __stg_add_args_author __stg_add_args_edit __stg_add_args_committer_date_is_author_date __stg_add_args_trailers subcmd_args+=( '(-n --name)'{-n,--name}'[name for imported patch]' '(-p --strip)'{-p+,--strip=}'[remove N leading directories from diff paths]:num' '--directory[prepend root to all filenames]:root:_directories' '(-t --stripname)'{-t,--stripname}'[strip number and extension from patch name]' '-C=[ensure N lines of surrounding context for each change]:num' '(-3 --3way)'{-3,--3way}'[attempt three-way merge]' '(-i --ignore)'{-i,--ignore}'[ignore applied patches in series]' '--replace[replace unapplied patches in series]' '--reject[leave rejected hunks in .rej files]' '--keep-cr[do not remove CR from email lines ending with CRLF]' '--message-id[create Message-ID trailer from email header]' '(-d --showdiff)'{-d,--showdiff}'[show patch content in editor buffer]' ':file:_files' + '(source)' '(-m --mail)'{-m,--mail}'[import from standard email file]' '(-M --mbox)'{-M,--mbox}'[import from mbox file]' '(-S --series)'{-S,--series}'[import from series file]' '(-u --url)'{-u,--url}'[import patch from URL]' ) _arguments -s -S $subcmd_args } _stg-init() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch _arguments -s $subcmd_args } _stg-log() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch subcmd_args+=( '--clear[clear log history]' '(-d --diff)'{-d,--diff}'[show refresh diffs]' '(-f --full)'{-f,--full}'[show full commit ids]' '(-g --graphical)'{-g,--graphical}'[show log in gitk]' '(-n --number)'{-n+,--number=}'[limit to number of commits]' '*:patches:__stg_dedup_inside_arguments __stg_patchrange --all' ) _arguments -s -S $subcmd_args } _stg-new() { local curcontext=$curcontext state line ret=1 local -a subcmd_args declare -A opt_args __stg_add_args_help __stg_add_args_color __stg_add_args_edit __stg_add_args_author __stg_add_args_trailers __stg_add_args_hook __stg_add_args_savetemplate subcmd_args+=( '(-d --diff)'{-d,--diff}'[show diff when editing patch message]' '(-n --name)'{-n,--name=}'[name for new patch]:patchname' '(-r --refresh)'{-r,--refresh}'[refresh new patch]' '(-F --force)'{-F,--force}'[force refresh even if index is dirty]' '(-i --index)'{-i,--index}'[refresh from index instead of worktree]' '(-)--[start file arguments]: :->modified-file' ) if [[ $words[(I)--] = "0" && ${words[(I)-n|--name(=*|)]} = "0" ]]; then subcmd_args+=(':: :_guard "([^-]?#|)" patchname') fi __stg_add_args_message _arguments -C -s $subcmd_args && ret=0 case $state in (modified-file) __stg_dedup __stg_modified_files && ret=0 ;; esac return ret } _stg-next() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch _arguments -s -S $subcmd_args } _stg-patches() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch __stg_add_args_diffopt subcmd_args+=( '(-d --diff)'{-d,--diff}'[show diffs of given files]' '*:files:__stg_cached_files' ) _arguments -s -S $subcmd_args } _stg-pick() { local -a subcmd_args # TODO: complete --parent commit id __stg_add_args_help __stg_add_args_committer_date_is_author_date subcmd_args+=( '(-n --name)'{-n,--name=}'[name for picked patch]:name' '(-B --ref-branch)'{-B,--ref-branch=}'[pick patches from branch]: :__stg_stgit_branch_names' '(-r --revert)'{-r,--revert}'[revert given commit object]' '(-p --parent=)'{-p,--parent}'[use commit id as parent]:commit' '(-x --expose)'{-x,--expose}'[append imported commit id to patch log]' '--noapply[keep patch unapplied]' '*'{-f,--file=}'[only fold given file]: :_files' '*:patches:__stg_dedup_inside_arguments __stg_patchrange --use-ref-branch' + '(mode)' '--fold[fold the commit into current patch]' '--update[fold limited to current patch files]' ) _arguments -s -S $subcmd_args } _stg-pop() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_keep subcmd_args+=( '(-s --spill)'{-s,--spill}'[pop a patch keeping its modifications in the tree]' - group-number '(-n --number)'{-n+,--number=}'[push specified number of patches]:number' - group-all '(-a --all)'{-a,--all}'[push all unapplied patches]' - group-patches '*:applied patches:__stg_dedup_inside_arguments __stg_patchrange --applied' ) _arguments -s -S $subcmd_args } _stg-prev() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch _arguments -s -S $subcmd_args } _stg-pull() { local -a subcmd_args __stg_add_args_help __stg_add_args_merged __stg_add_args_push_conflicts subcmd_args+=( '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]' ':repository:__stg_remotes' ) _arguments -s -S $subcmd_args } _stg-push() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_keep __stg_add_args_merged __stg_add_args_committer_date_is_author_date __stg_add_args_push_conflicts subcmd_args+=( '--reverse[push patches in reverse order]' '--noapply[push without applying]' '--set-tree[push patch with the original tree]' - group-all '(-a --all)'{-a,--all}'[push all unapplied patches]' - group-number '(-n --number)'{-n+,--number=}'[push specified number of patches]:number' - group-patches '*:unapplied patches:__stg_dedup_inside_arguments __stg_patchrange --unapplied' ) _arguments -s -S $subcmd_args } _stg-rebase() { local -a subcmd_args __stg_add_args_help __stg_add_args_merged __stg_add_args_committer_date_is_author_date __stg_add_args_push_conflicts subcmd_args+=( '(-n --nopush)'{-n,--nopush}'[do not push patches after rebasing]' '(-i --interactive)'{-i,--interactive}'[interactively manipulate patches in editor]' '--autostash[Stash changes before rebase and reapply them after]' ':new-base-id:__stg_heads' ) _arguments -s -S $subcmd_args } _stg-redo() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '--hard[discard changes in index/worktree]' '(-n --number)'{-n+,--number=}'[number of undos to redo]:number' ) _arguments -s -S $subcmd_args } _stg-refresh() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_author __stg_add_args_edit __stg_add_args_committer_date_is_author_date __stg_add_args_hook __stg_add_args_trailers __stg_add_args_diffopt __stg_add_args_push_conflicts subcmd_args+=( '(-a --annotate)'{-a,--annotate=}'[annotate patch log entry]:note' '(-d --diff)'{-d,--diff}'[show diff when editing patch message]' '(-F --force)'{-F,--force}'[force refresh even if index is dirty]' '(-i --index)'{-i,--index}'[refresh from index instead of worktree]' '(-p --patch)'{-p,--patch=}'[refresh patch other than top patch]: :__stg_patch --all' '--spill[Spill patch contents to worktree and index, and erase patch content]' + '(update-files)' '(-u --update)'{-u,--update}'[only update current patch files]' '*:files:__stg_modified_files' + '(submodules)' '(-s --submodules)'{-s,--submodules}'[include submodules in refresh]' '--no-submodules[exclude submodules from refresh]' ) __stg_add_args_message _arguments -s -S $subcmd_args } _stg-rename() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch __stg_add_args_color subcmd_args+=( ':old-patch:__stg_patch --all' ':new patch name:' ) _arguments -s -S $subcmd_args } _stg-repair() { local -a subcmd_args __stg_add_args_help _arguments -s $subcmd_args } _stg-reset() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '--hard[discard changes in index/worktree]' ':state:' '*:patches:__stg_dedup_inside_arguments __stg_patchrange --all' ) _arguments -s -S $subcmd_args } _stg-series() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch __stg_add_args_color subcmd_args+=( '--author[display the author name for each patch]' '(-c --count)'{-c,--count}'[print number of patches]' '(-i --commit-id)'{-i,--commit-id}=-'[display commit ids]::length' '(-d --description)'{-d,--description}'[display short descriptions]' '(-e --empty)'{-e,--empty}'[identify empty patches]' '(-I --indices)'{-I,--indices}'[display absolute indices of patches]' '(-m --missing)'{-m,--missing=}'[show patches from branch missing in current]: :__stg_stgit_branch_names' '(-O --offsets)'{-O,--offsets}'[display relative offsets of patches]' '--prefix[display patch status prefix]' '(-P --no-prefix)'{-P,--no-prefix}'[do not display the patch status prefix]' '(-r --reverse)'{-r,--reverse}'[display in reverse order]' '(-s --short)'{-s,--short}'[list just patches around the topmost patch]' '--showbranch[display branch name of listed patches]' '--no-author[do not display patch author]' '--no-commit-id[do not display commit ids]' '--no-description[do not display patch descriptions]' '--no-empty[do not identify empty patches]' '--no-indices[do not display patch indices]' '--no-offsets[do not display patch offsets]' '--no-reverse[do not display in reverse order]' '--no-showbranch[do not display branch name]' - group-ahu '(-A --applied)'{-A,--applied}'[show applied patches]' '(-H --hidden)'{-H,--hidden}'[show hidden patches]' '(-U --unapplied)'{-U,--unapplied}'[show unapplied patches]' - group-all '(-a --all)'{-a,--all}'[show all patches including hidden]' - group-patches '*:patches:__stg_dedup_inside_arguments __stg_patchrange --all --suggest-range' ) _arguments -s -S $subcmd_args } _stg-show() { local -a subcmd_args local curcontext=$curcontext state line ret=1 declare -A opt_args __stg_add_args_help __stg_add_args_branch __stg_add_args_diffopt subcmd_args+=( '(*)'{-p,--patch=}'[patch or revision to show]: :__stg_dedup_inside_arguments __stg_patchrange --all' '(-s --stat)'{-s,--stat}'[show diff stat]' '(-)--[start file arguments]: :->cached-files' '(-A --applied *)'{-A,--applied}'[show applied patches]' '(-U --unapplied *)'{-U,--unapplied}'[show unapplied patches]' '(-H --hidden *)'{-H,--hidden}'[show hidden patches]' '(-A --applied -U --unapplied -H --hidden -p --patch)*:patches:__stg_dedup_inside_arguments __stg_patchrange --all' ) _arguments -C -s $subcmd_args && ret=0 case $state in (cached-files) __stg_dedup __stg_cached_files ;; esac return ret } _stg-sink() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_keep __stg_add_args_committer_date_is_author_date subcmd_args+=( '(-n --nopush)'{-n,--nopush}'[do not push patches after sinking]' '(-T --above -t --to --below)'{-t,--to=,--below=}'[sink patches below target patch]: :__stg_patch --applied' '(-T --above -t --to --below)'{-T,--above=}'[sink patches above target patch]: :__stg_patch --applied' '*:patches:__stg_dedup_inside_arguments __stg_patchrange' ) _arguments -s -S $subcmd_args } _stg-spill() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_committer_date_is_author_date subcmd_args+=( '(-a --annotate)'{-a,--annotate}'[annotate patch log entry]:annotation' '(-r --reset)'{-r,--reset}'[also reset the index]' '(-)--[start file arguments]: :->patch-files' '*:: :->patch-files' ) _arguments -C -s $subcmd_args && ret=0 case $state in (patch-files) __stg_dedup __stg_patch_files ;; esac return ret } _stg-squash() { local -a subcmd_args __stg_add_args_help __stg_add_args_author __stg_add_args_edit __stg_add_args_committer_date_is_author_date __stg_add_args_hook __stg_add_args_savetemplate __stg_add_args_trailers subcmd_args+=( '(-n --name)'{-n,--name=}'[name for squashed patch]: :__stg_patch --all' '*:patches:__stg_dedup_inside_arguments __stg_patch --all' ) __stg_add_args_message _arguments -s -S $subcmd_args } _stg-sync() { local -a subcmd_args __stg_add_args_help __stg_add_args_committer_date_is_author_date subcmd_args+=( + '(patches)' '(-a --all)'{-a,--all}'[synchronize all applied patches]' '*:patches:__stg_dedup_inside_arguments __stg_patchrange --suggest-range --use-ref-branch' + '(source)' '(-B --ref-branch)'{-B,--ref-branch}'[synchronize patches with branch]: :__stg_stgit_branch_names' '(-S --series)'{-S,--series=}'[synchronize patches with series]: :_files' ) _arguments -s -S $subcmd_args } _stg-top() { local -a subcmd_args __stg_add_args_help __stg_add_args_color __stg_add_args_branch _arguments -s -S $subcmd_args } _stg-uncommit() { local -a subcmd_args __stg_add_args_help subcmd_args+=( - group-number '(-n --number)'{-n+,--number=}'[push specified number of patches]:number' ':prefix:' - group-to '(-t --to)'{-t,--to=}'[uncommit to the specified commit]:commit' '(-x --exclusive)'{-x,--exclusive}'[exclude the commit specified by --to]' - group-names '*: :_guard "([^-]?#|)" names' ) _arguments -s -S $subcmd_args } _stg-undo() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '--hard[discard changes in index/worktree]' '(-n --number)'{-n+,--number=}'[number commands to undo]:number' ) _arguments -s -S $subcmd_args } _stg-unhide() { local -a subcmd_args __stg_add_args_help __stg_add_args_branch subcmd_args+=( ':patches:__stg_dedup_inside_arguments __stg_patchrange --hidden' ) _arguments -s -S $subcmd_args } _stg-version() { local -a subcmd_args __stg_add_args_help subcmd_args+=( '(-s --short)'{-s,--short}'[show abbreviated version information]' ) _arguments -s -S $subcmd_args } __stg_add_args_author() { subcmd_args+=( '--author=[set author details]' '--authdate=[set author date]:date' '--authemail=[set author email]:email' '--authname=[set author name]:name' ) } __stg_add_args_branch() { subcmd_args+=( '(-b --branch)'{-b,--branch=}'[specify another branch]: :__stg_stgit_branch_names' ) } __stg_add_args_color() { subcmd_args+=( '--color=-[when to colorize output]:when:(( auto\:"color when outputting to a TTY" always\:"always use color" ansi\:"force color with ANSI escape sequences" never\:"never use color"))' ) } __stg_add_args_diffopt() { subcmd_args+=( '*'{-O+,--diff-opt=}'[extra option for git diff]:opt:__stg_git_diff_opts' ) } __stg_add_args_edit() { subcmd_args+=( '(-e --edit)'{-e,--edit}'[invoke interactive editor]' ) } __stg_add_args_help() { subcmd_args+=( '(- *)'{-h,--help}'[show help message and exit]' ) } __stg_add_args_hook() { subcmd_args+=( '--no-verify[disable commit-msg hook]' ) } __stg_add_args_keep() { subcmd_args+=( '(-k --keep)'{-k,--keep}'[keep local changes]' ) } __stg_add_args_merged() { subcmd_args+=( '(-m --merged)'{-m,--merged}'[check for patches merged upstream]' ) } __stg_add_args_push_conflicts() { subcmd_args+=( '--conflicts=-[allow pushing patches that may result in merge conflicts]:policy:(( allow\:"allow pushing patches with conflicts" disallow\:"disallow pushing patches with conflicts"))' ) } __stg_add_args_message() { subcmd_args+=( + '(message)' '(-f --file)'{-f,--file=}'[use message file instead of invoking editor]: :_files' '(-m --message)'{-m,--message=}'[specify message instead of invoking editor]:message' ) } __stg_add_args_savetemplate() { subcmd_args+=( '--save-template=[save message template to file and exit]: :_files' ) } __stg_add_args_trailers() { subcmd_args+=( '--ack=-[add Acked-by trailer]' '--review=-[add Reviewed-by trailer]' '--signoff=-[add Signed-off-by trailer]' ) } __stg_add_args_committer_date_is_author_date() { subcmd_args+=( '--committer-date-is-author-date[use author date as committer date]' '--cdiad[use author date as committer date]' ) } __stg_complete_git_opts() { local git_cmd short long i git_cmd=$1 short=$2 long=$3 # Parse short and long options (e.g. -O and --diff-opt) from $words. declare -a git_opts git_opts_after zmodload -F 'zsh/zutil' 'b:zparseopts' () { zparseopts -E -D -a git_opts ${short}+: -${long}+: 2>/dev/null; } \ ${(@)words[1,CURRENT]} () { zparseopts -E -D -a git_opts_after ${short}+: -${long}+: 2>/dev/null; } \ ${(@)words[CURRENT+1,-1]} # Compose git command line words=('git' ${(@)__stg_C_args} ${git_cmd}) # The option values are at the even indexes in the git_opts array. # The last option is skipped because it is the partially specified one being # completed. if (( $#git_opts > 2 )); then for i in {1..$(($#git_opts - 2))..2}; do # Need to strip any leading '=' because zparseopts will parse, for example, # `--diff-opt=foo` as ('--diff-opt' '=foo'). words+=(${git_opts[i+1]#=}) done fi # If the user has not started typing the value, prime it with '-' to force # completing only the options (and not arguments) to the git command. : ${SUFFIX:-${PREFIX:=-}} words+=("$PREFIX$SUFFIX") (( CURRENT = $#words )) if (( $#git_opts_after > 2 )); then for i in {1..$(($#git_opts_after - 2))..2}; do words+=(${git_opts_after[i+1]#=}) done fi _message -e "git-$git_cmd-option" "git $git_cmd" && _dispatch git git $commands[git] } __stg_git_diff_opts() { __stg_complete_git_opts diff-tree O diff-opt } __stg_git_format_patch_opts() { __stg_complete_git_opts format-patch G git-opt } __stg_git_send_email_opts() { __stg_complete_git_opts send-email G git-opt } __stg_revisions () { _alternative \ "heads::__stg_heads" \ "commit-tags::__stg_commit_tags" \ "patch-refs::__stg_patch_refs" } __stg_commit_tags () { local expl declare -a tags tags=(${${(M)${(f)"$(_call_program commit-tag-refs "git ${__stg_C_args} for-each-ref --format='%(*objecttype)%(objecttype) %(refname)' refs/tags 2>/dev/null")"}:#commit(tag|) *}#commit(tag|) refs/tags/}) __stg_git_command_successful $pipestatus || return 1 _wanted commit-tags expl "commit tag" compadd -M 'r:|/=* r:|=*' "$@" -o numeric -a - tags } __stg_patch_refs () { local expl declare -a refs refs=(${(f)"$(_call_program patch-refs "git ${__stg_C_args} for-each-ref --format='%(refname:lstrip=2)' refs/patches 2>/dev/null")"}) __stg_git_command_successful $pipestatus || return 1 _wanted commit-tags expl "patch ref" compadd -p refs/patches/ -M 'r:|/=* r:|=*' "$@" -o numeric -a - refs } __stg_heads () { _alternative 'heads-local::__stg_heads_local' 'heads-remote::__stg_heads_remote' } __stg_heads_local () { local f gitdir declare -a heads heads=(${(f)"$(_call_program headrefs git ${__stg_C_args} for-each-ref --format='"%(refname:short)"' refs/heads 2>/dev/null)"}) gitdir=$(_call_program gitdir git rev-parse --git-dir 2>/dev/null) if __stg_git_command_successful $pipestatus; then for f in HEAD FETCH_HEAD ORIG_HEAD MERGE_HEAD; do [[ -f $gitdir/$f ]] && heads+=$f done [[ -f $gitdir/refs/stash ]] && heads+=stash [[ -f $gitdir/refs/bisect/bad ]] && heads+=bisect/bad fi __stg_git_describe_commit heads heads-local "local head" "$@" } __stg_heads_remote () { declare -a heads heads=(${(f)"$(_call_program headrefs git ${__stg_C_args} for-each-ref --format='"%(refname:short)"' refs/remotes 2>/dev/null)"}) __stg_git_describe_commit heads heads-remote "remote head" "$@" } __stg_command_successful () { if (( ${#*:#0} > 0 )); then _message 'not a StGit branch' return 1 fi return 0 } __stg_git_command_successful () { if (( ${#*:#0} > 0 )); then _message 'not a git repository' return 1 fi return 0 } __stg_config_sections () { local regex tag desc local -a groups regex=$1 tag=$2 desc=$3 groups=(${${${(0)"$(_call_program $tag "git ${__stg_C_args} config -z --get-regexp -- ${(q)regex}")"}#*.}%%.[^.]##$'\n'*}) _describe -t $tag $desc groups } __stg_email_send_identities () { __stg_config_sections '^sendemail\..+\.[^.]+$' identities 'sendemail identity' } __stg_git_describe_commit () { __stg_git_describe_branch $1 $2 $3 -M 'r:|/=* r:|=*' "${(@)argv[4,-1]}" } __stg_git_describe_branch () { local __commits_in=$1 local __tag=$2 local __desc=$3 shift 3 integer maxverbose if zstyle -s :completion:$curcontext: max-verbose maxverbose && (( ${compstate[nmatches]} <= maxverbose )); then local __c local -a __commits for __c in ${(P)__commits_in}; do __commits+=("${__c}:${$(_call_program describe git ${__stg_C_args} rev-list -1 --oneline $__c)//:/\\:}") done _describe -t $__tag $__desc __commits "$@" else local expl _wanted $__tag expl $__desc compadd "$@" -a - $__commits_in fi } __stg_stgit_branch_names () { local expl declare -a branch_names stgit_branches=( ${${(f)"$(_call_program branchrefs git ${__stg_C_args} for-each-ref --format='"%(refname)"' refs/stacks 2>/dev/null)"}#refs/stacks/} ) __stg_git_command_successful $pipestatus || return 1 __stg_git_describe_commit stgit_branches branch-names 'stgit branch name' "$@" } __stg_git_branch_names () { local expl declare -a branch_names branch_names=(${${(f)"$(_call_program branchrefs git for-each-ref --format='"%(refname)"' refs/heads 2>/dev/null)"}#refs/heads/}) __stg_git_command_successful $pipestatus || return 1 __stg_git_describe_commit branch_names branch-names 'branch name' "$@" } __stg_files_relative() { local prefix prefix=$(_call_program gitprefix git ${__stg_C_args} rev-parse --show-prefix 2>/dev/null) if (( $#prefix == 0 )); then print $1 return fi local file local -a files files=() # Collapse "//" and "/./" into "/". Strip any remaining "/." and "/". for file in ${${${${${(0)1}//\/\///}//\/.\///}%/.}%/}; do integer i n (( n = $#file > $#prefix ? $#file : $#prefix )) for (( i = 1; i <= n; i++ )); do if [[ $file[i] != $prefix[i] ]]; then while (( i > 0 )) && [[ $file[i-1] != / ]]; do (( i-- )) done break fi done files+=${(l@${#prefix[i,-1]//[^\/]}*3@@../@)}${file[i,-1]} done print ${(pj:\0:)files} } __stg_files () { local compadd_opts opts tag description gitcdup gitprefix files expl zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F: zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed x+: --exclude+: tag=$1 description=$2; shift 2 gitcdup=$(_call_program gitcdup git ${__stg_C_args} rev-parse --show-cdup 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 gitprefix=$(_call_program gitprefix git ${__stg_C_args} rev-parse --show-prefix 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 # TODO: --directory should probably be added to $opts when --others is given. local pref=$gitcdup$gitprefix$PREFIX # First allow ls-files to pattern-match in case of remote repository files=(${(0)"$(_call_program files git ${__stg_C_args} ls-files -z --exclude-standard ${(q)opts} -- ${(q)${pref:+$pref\*}:-.} 2>/dev/null)"}) __stg_git_command_successful $pipestatus || return # If ls-files succeeded but returned nothing, try again with no pattern if [[ -z "$files" && -n "$pref" ]]; then files=(${(0)"$(_call_program files git ${__stg_C_args} ls-files -z --exclude-standard ${(q)opts} -- 2>/dev/null)"}) __stg_git_command_successful $pipestatus || return fi # _wanted $tag expl $description _files -g '{'${(j:,:)files}'}' $compadd_opts - _wanted $tag expl $description _multi_parts -f $compadd_opts - / files } __stg_cached_files () { __stg_files --cached cached-files 'cached file' $* } __stg_modified_files () { __stg_files --modified modified-files 'modified file' $* } __stg_diff-index_files () { local tree=$1 description=$2 tag=$3; shift 3 local files expl # $tree needs to be escaped for _call_program; matters for $tree = "HEAD^" files=$(_call_program files git ${__stg_C_args} diff-index -z --name-only --no-color --cached ${(q)tree} 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 files=(${(0)"$(__stg_files_relative $files)"}) __stg_git_command_successful $pipestatus || return 1 _wanted $tag expl $description _multi_parts $@ - / files } __stg_changed-in-index_files () { __stg_diff-index_files HEAD 'changed in index file' changed-in-index-files "$@" } __stg_changed-in-working-tree_files () { local files expl files=$(_call_program changed-in-working-tree-files git ${__stg_C_args} diff -z --name-only --no-color 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 files=(${(0)"$(__stg_files_relative $files)"}) __stg_git_command_successful $pipestatus || return 1 _wanted changed-in-working-tree-files expl 'changed in working tree file' _multi_parts $@ -f - / files } __stg_changed_files () { _alternative \ 'changed-in-index-files::__stg_changed-in-index_files' \ 'changed-in-working-tree-files::__stg_changed-in-working-tree_files' } __stg_patch_files () { local files expl top_id top_id=$(_call_program id stg ${__stg_C_args} id 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 files=$(_call_program patch-files git ${__stg_C_args} diff -z --name-only --no-color $top_id~ $top_id 2>/dev/null) __stg_git_command_successful $pipestatus || return 1 files=(${(0)"$(__stg_files_relative $files)"}) __stg_git_command_successful $pipestatus || return 1 _wanted patch-files expl "patch files" _multi_parts $@ -f - / files } __stg_get_branch_opt() { local use_ref_branch short long i zparseopts -- -use-ref-branch=use_ref_branch if [[ -n "$use_ref_branch" ]]; then short="-B" long="--ref-branch" else short="-b" long="--branch" fi i=${words[(I)$short|$long(=*|)]} if (( i > 0 )); then case ${words[i]} in $short|$long) if (( i < $#words )); then echo "--branch=${words[i + 1]}" fi ;; *) echo "--branch=${words[i]#*=}" ;; esac fi } __stg_patch() { declare -a compadd_opts zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F: local use_ref_branch branch_opt zparseopts -D -E -- -use-ref-branch=use_ref_branch branch_opt="$(__stg_get_branch_opt $use_ref_branch)" local expl declare -a patchlines patchnames local desc_flag zstyle -T ":completion:${curcontext}:" verbose && desc_flag="--description" patchlines=(${(f)"$(_call_program patches stg ${__stg_C_args} series $desc_flag $branch_opt $@ 2>/dev/null)"}) __stg_command_successful $pipestatus || return 1 local patchline for patchline in $patchlines; do patchnames+=("${(MS)${patchline[3,-1]%%\#*}##[[:graph:]]*[[:graph:]]}") done _wanted patches expl 'patch' compadd $compadd_opts -o nosort -l -d patchlines -a patchnames } __stg_patchrange() { # Remove/capture compadd options declare -a compadd_opts zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F: # Remove/capture patch selection, --suggest-range, and --use-ref-branch options declare -a selection_opt local use_ref_branch suggest_range branch_opt zparseopts -D -E -a selection_opt -- -suggest-range=suggest_range -use-ref-branch=use_ref_branch -applied -unapplied -hidden -all branch_opt="$(__stg_get_branch_opt $use_ref_branch)" # Consult zstyle to determine whether to use verbose patch listings local desc_flag zstyle -T ":completion:${curcontext}:" verbose && desc_flag="--description" local expl declare -a patchlines patchnames if compset -P '*..'; then if [[ $IPREFIX != ".." ]]; then # If the command line has 'patch..' (but not plain '..'), use that # open-ended range as the selection. N.B. any leading '--option=' is # trimmed. This affects, e.g. `stg diff --range`. selection_opt=("${IPREFIX#--*=}") fi # Otherwise for plain '..', we leave the nominal selection as-is. elif [[ -n "$suggest_range" ]]; then # If --suggest-range is specified, suffix the initial patch with '..' to start a # range. compadd_opts+=(-S ..) fi patchlines=(${(f)"$(_call_program patches stg ${__stg_C_args} series $desc_flag $branch_opt $selection_opt 2>/dev/null)"}) __stg_command_successful $pipestatus || return 1 local patchline for patchline in $patchlines; do patchnames+=("${(MS)${patchline[3,-1]%%\#*}##[[:graph:]]*[[:graph:]]}") done _wanted patches expl 'patch' compadd $compadd_opts -o nosort -l -d patchlines -a patchnames } __stg_remotes() { local remotes expl remotes=(${(f)"$(_call_program remotes git ${__stg_C_args} remote 2>/dev/null)"}) __stg_git_command_successful $pipestatus || return 1 _wanted remotes expl remote compadd "$@" -a - remotes } __stg_subcommands() { local -a command_list command_list=(${(f)"$(_call_program commands stg ${__stg_C_args} completion list commands-and-aliases --style=zsh)"}) __stg_git_command_successful $pipestatus || return 1 _describe -t commands 'stgit command' command_list } # Used to filter already-used completions. __stg_dedup () { local -a ignored=(${line:#${words[CURRENT]}}) $* -F ignored } # Like __stg_dedup, but for use inside _arguments specs. __stg_dedup_inside_arguments () { declare -a compadd_opts zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F: __stg_dedup $* $compadd_opts } _stgit() { integer ret=1 local curcontext="$curcontext" state line typeset -A opt_args _arguments -0 -C \ '(- :)--help[print help information]' \ '(- :)--version[display version information]' \ '*-C[run as if stg was started in given path]: :_directories' \ '--color=-[when to colorize output]:when:(( auto\:"color when outputting to a TTY" always\:"always use color" ansi\:"force color with ANSI escape sequences" never\:"never use color"))' \ '(-): :->command' \ '(-)*:: :->option-or-argument' && ret=0 local -a __stg_C_args __stg_C_dirs local p for p in ${(0)opt_args[-C]}; do __stg_C_args+=("-C" "$p") __stg_C_dirs+=("$p") done unset p case $state in (command) __stg_subcommands && ret=0 ;; (option-or-argument) local a local -a alias_list alias_list=(${(f)"$(_call_program alias-list stg ${__stg_C_args} completion list aliases --show-expansion --style=zsh)"}) __stg_git_command_successful $pipestatus || return 1 for a in $alias_list; do if [[ $words[1] = "${a%%:*}" ]]; then local -a aliasexp tmpwords aliasexp=(${(z)"${a#*:}"}) tmpwords=($aliasexp) [[ -z "${words[2,-1]}" ]] || tmpwords+=(${words[2,-1]}) [[ -n ${words[CURRENT]} ]] || tmpwords+=('') (( CURRENT += ${#aliasexp} - 1 )) words=("${tmpwords[@]}") unset aliasexp tmpwords if [[ $words[1] = \!* ]]; then words[1]=${words[1]##\!} local p integer push_count=0 for p in ${__stg_C_dirs}; do pushd -q $p && (( push_count++ )) done _normal && ret=0 while (( push_count )); do popd -q (( push_count-- )) done unset p push_count return ret fi break fi done unset a alias_list curcontext=${curcontext%:*:*}:stg-$words[1]: local -a subcmd_args if ! _call_function ret _stg-$words[1]; then if zstyle -T :completion:$curcontext: use-fallback; then _default && ret=0 else _message "unknown subcommand: $words[1]" fi fi ;; esac return ret } _stgit stgit-2.6.0/contrib/000077500000000000000000000000001520252120500143035ustar00rootroot00000000000000stgit-2.6.0/contrib/.gitignore000066400000000000000000000000061520252120500162670ustar00rootroot00000000000000*.elc stgit-2.6.0/contrib/Makefile000066400000000000000000000006011520252120500157400ustar00rootroot00000000000000prefix ?= $(HOME)/.local DESTDIR ?= INSTALL ?= install all: $(MAKE) -C vim all install: install-emacs install-vim install-emacs: stgit.el $(INSTALL) -d $(DESTDIR)$(prefix)/share/emacs/site-lisp $(INSTALL) -m 0644 $< $(DESTDIR)$(prefix)/share/emacs/site-lisp install-vim: $(MAKE) -C vim install clean: $(MAKE) -C vim clean .PHONY: all clean install install-emacs install-vim stgit-2.6.0/contrib/release/000077500000000000000000000000001520252120500157235ustar00rootroot00000000000000stgit-2.6.0/contrib/release/README000066400000000000000000000023341520252120500166050ustar00rootroot00000000000000StGit Release Checklist ======================= 0. Test - All functional tests should be passing (`make test`) - All lints should be passing (`make lint`) 1. Update CHANGELOG.md - Look at git log from last release to HEAD. Identify user-facing changes, but ignore internal-only changes such as refactorings. - Add changes to *Removed*, *Added*, *Changed*, and *Fixed* lists in CHANGELOG.md. - Change "[Unreleased]" to reflect new release version and date. - Commit updated CHANGELOG.md 2. Update version in Cargo.toml - Update the version field: `version = "X.Y.Z"` 3. Create new tag - `git tag --sign -m 'Release vX.Y.Z' vX.Y.Z` 4. Update stacked-git.github.io - In stacked-git.github.io repo, `make sync` to sync updated changelog and man pages into website. - Review home page for anything that should be updated in conjunction with the StGit release. 5. Push changes upstream - Push new tag and master branch upstream - Push stacked-git.github.io changes 6. Publish GitHub Release - Draft release is created for new tags. - Change release title to "Stacked Git X.Y.Z" 7. Publish to crates.io - `cargo publish` 8. Review and update these release instructions stgit-2.6.0/contrib/release/latest-changelog.awk000077500000000000000000000010761520252120500216570ustar00rootroot00000000000000#!/usr/bin/env -S awk -f # Extract the latest release notes from CHANGELOG.md. # # The h3 sections from the first h2 section are printed. BEGIN { foundFirstH2 = 0 foundFirstH3 = 0 foundSecondH2 = 0 } { if (!foundFirstH2) { if ($0 ~ /^## /) { foundFirstH2 = 1 } } else if (!foundFirstH3) { if ($0 ~ /^### /) { foundFirstH3 = 1 print $0 } } else if (!foundSecondH2) { if ($0 ~ /^## /) { foundSecondH2 = 1 } else { print $0 } } } stgit-2.6.0/contrib/release/make-archive.sh000077500000000000000000000004211520252120500206130ustar00rootroot00000000000000#!/bin/sh set -eu OUTPUT_DIR=${1:-.} TAG=$(git describe --match 'v*.*.*' --exact-match) VER=${TAG#v} ARCHIVE="stgit-${VER}.tar.gz" git archive --format=tar.gz --prefix="stgit-${VER}/" -o "${OUTPUT_DIR}/${ARCHIVE}" "${TAG}" printf "%s/%s\n" "${OUTPUT_DIR}" "${ARCHIVE}" stgit-2.6.0/contrib/stg-cvs000077500000000000000000000116431520252120500156240ustar00rootroot00000000000000#!/bin/bash set -e # stg-cvs - helper script to manage a mixed cvs/stgit working copy. # Allows quick synchronization of a cvs mirror branch (does not try to # reconstruct patchsets, creates "jumbo" commits), and commits stgit # patches to CVS. # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. # NOTES # - you want to add a "CVS" line to .git/info/exclude # - you may want to add a ".git" line to the top .cvsignore # BRANCH INIT # - ensure the cvs wc is clean (eg. with "cvsco") # $ git init # $ echo CVS >> .git/info/exclude # $ git add . # $ git commit -m "Initial import." # $ git branch -m master cvs # $ stg branch -c master cvs # $ git config branch.master.stgit.parentbranch cvs (0.12.1 and earlier only) # $ git config branch.cvs.description "CVS $(cat CVS/Root) $(cat CVS/Repository) $(cat CVS/Tag 2>/dev/null | echo HEAD)" # $ git config branch.master.description "Changes for $(cat CVS/Repository) $(cat CVS/Tag 2>/dev/null | echo HEAD)" # LIMITATIONS # - this is only a proof-of-concept prototype # - lacks an "init" command (see above) # - "commit" does not ensure the base is up-to-date before trying to # commit (but hey, it's CVS ;): better "stg-cvs pull" first # - "commit" can only commit a single patch # - not much robustness here # - still no support for files removed in cvs (should catch "no # longer in the repository" message) # - this only deals with CVS but could surely be extended to any other # VCS # - lacks synchronisation of .cvsignore <-> .gitignore # - no support for filenames with spaces (stg lacks --zero output format) # - git commit is too chatty when it finds nothing to commit # - lacks a "quick cvs commit" feature # DESIGN FLAWS # - while fetching, if a file change was not git update-index'd when # cvs-update'd (eg. because of a stg-cvs bug), it is not seen on further # fetches until it changes again, since we scan "cvs update" output. # This yields possible inconsistencies with CVS. # - similarly, any conflict while cvs-updating (whether due to illegal # changes to the cvs-mirror-branch, or due to files added to cvs but # already-existing in working copy, or to directory moves inside the # cvs repository, or ) has to be dealt with by hand (although # the situation is better here: cvs sees the conflict on subsequent tries) # - bad/no support for cvsutils: # - stg push/pop operations confuse cvsu because of timestamp changes # - cvspurge/cvsco would nuke .git => does not make it easy to ensure # synchronisation # - should use a separate workspace for cvs branch like tailor does # - confused by cvs keyword substitution usage() { [ "$#" = 0 ] || echo "ERROR: $*" echo "Usage: $(basename $0) " echo " commands: $(do_commands)" exit 1 } do_commands() { echo $(grep '^[a-z-]*)' $0 | cut -d')' -f1) } do_fetch() { local return=0 local path local parent="$1" local branch="$2" # record changes from cvs into index stg branch "$parent" || exit $? cvs -fq update -dP | grep -v '^\? ' | tee /dev/tty | while read status path; do if [ -e "$path" ]; then git update-index --add "$path" || exit $? else git update-index --remove "$path" || exit $? fi # cvs update: `FELIN1_PEP/src/java/com/sagem/felin/ui/widget/PEPRifStateIcon.java' is no longer in the repository done # create commit if git commit -m "stg-cvs sync"; then : else return=$? fi # back to branch stg branch "$branch" || exit $? return $return } cvs_add_dir() { local parent=$(dirname "$1") if [ ! -e "$parent/CVS" ]; then cvs_add_dir "$parent" fi cvs add "$1" } # get context branch=$(stg branch) parent=$(git config "branch.${branch}.stgit.parentbranch") || usage "no declared parent for '$branch' - set branch.${branch}.stgit.parentbranch" # extract command [ "$#" -ge 1 ] || usage command="$1" shift case "$command" in fetch) do_fetch "$parent" "$branch" ;; pull) if do_fetch "$parent" "$branch"; then # update # --merged stg rebase "$parent" stg clean --applied fi ;; commit) # sanity asserts [ $(stg applied | wc -l) = 1 ] || usage "you don't have exactly one patch applied" # context patch=$(stg top) # adds stg files | grep ^A | cut -c3- | while read file; do parent=$(dirname "$file") if [ ! -e "$parent/CVS" ]; then cvs_add_dir "$parent" fi cvs -f add "$file" done # removes stg files | grep ^D | cut -c3- | xargs -r cvs -f remove # commit stg files --bare | xargs -r cvs -fq commit \ -F ".git/patches/$branch/patches/$patch/description" # sync the parent branch stg branch "$parent" git cherry-pick "patches/${branch}/${patch}" stg branch "${branch}" # update # --merged stg rebase "$parent" stg clean --applied ;; _commands) # hint for bash-completion people :) do_commands ;; *) usage "unknown command '$command'" ;; esac stgit-2.6.0/contrib/stg-gitk000077500000000000000000000047561520252120500157760ustar00rootroot00000000000000#!/bin/sh set -e # stg-gitk - helper script to graphically display an StGit stack # Displays given branches and stacks, without getting disturbed by # patch logs. # LIMITATIONS: # - no support for spaces in branch names # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. helptext="Usage: $(basename "$0") [--refs] [|--all] [-- ]" usage() { echo >&2 "$helptext" exit 1 } allbranches=0 refsonly=0 branches='' while [ "$#" -gt 0 ]; do case "$1" in --refs) refsonly=1 ;; --all) allbranches=1 ;; --help) echo "$helptext"; exit 0 ;; --) shift; break ;; --*) usage ;; *) branches="$branches $1" ;; esac shift done # Now any remaining stuff in $@ are additional options for gitk if [ $allbranches = 1 ] && [ "$branches" != "" ]; then usage fi GIT_DIR=$(git rev-parse --git-dir) GIT_DIR_SKIPLEN=$(printf "%s/X" "$GIT_DIR" | wc -c) refdirs='' if [ $allbranches = 1 ]; then refdirs="$GIT_DIR/refs" else # default to current branch if [ "$branches" = "" ]; then branches="$(stg branch)" fi if [ "$branches" = "" ]; then echo >&2 "ERROR: cannot find current branch." exit 1 fi # expand patches for each named branch for b in $branches; do if [ -e "$GIT_DIR/refs/patches/$b" ]; then # StGit branch: show all patches refdirs="$refdirs $GIT_DIR/refs/heads/$b $GIT_DIR/refs/patches/$b" elif [ -e "$GIT_DIR/refs/heads/$b" ]; then # other Git branch refdirs="$refdirs $GIT_DIR/refs/heads/$b" elif [ "$(git for-each-ref "refs/$b" | wc -l)" != 0 ]; then # other ref refdirs="$refdirs $(git for-each-ref --format="$GIT_DIR/%(refname)" "refs/$b")" else echo >&2 "ERROR: no such ref '$b'" usage fi done fi printrefs() { # shellcheck disable=SC2086 find $refdirs -type f -not -name '*.log' | cut -c"${GIT_DIR_SKIPLEN}"- } if [ $refsonly = 1 ]; then printrefs elif grep -q -- --argscmd "$(command -v gitk)"; then # This gitk supports --argscmd. # Let's use a hack to pass --all, which was consumed during command-line parsing if [ $allbranches = 1 ]; then gitk --argscmd="$0 --refs --all" "$@" else gitk --argscmd="$0 --refs $branches" "$@" fi else # This gitk does not support --argscmd, just compute refs once # shellcheck disable=SC2046 gitk $(printrefs) "$@" fi stgit-2.6.0/contrib/stg-k000077500000000000000000000017371520252120500152660ustar00rootroot00000000000000#!/bin/sh set -e # stg-k - execute given StGit command while preserving local changes # Uses a temporary patch to save local changes, then execute the given # command, and restore local changes from the saved patch. In # essence, "stg-k pop" is a "stg pop -k" that works better, hence its # name. # CAVEATS: # - this script relies on the operation to run ignoring hidden # patches, so in 0.12 (where "stg push" can push an hidden patch) # "stg-k push" will fail midway, albeit with no information loss - # you'll just have to finish manually. This is fixed in 0.13 # - running this script to pop all patches in the stack fails, since # stg-unnew does not support this case. # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. stg new __local -m " - local changes (internal patch)" stg refresh stg pop # avoid bad interactions like "stg-k push" not behaving as expected stg hide __local stg "$@" stg unhide __local stg push __local stg-unnew stgit-2.6.0/contrib/stg-mdiff000077500000000000000000000020331520252120500161070ustar00rootroot00000000000000#!/bin/bash set -e # stg-mdiff - display meta-diffs, ie. diffs of diffs # Main use: show evolutions of a patch. # eg. stg-mdiff foo@stable foo # stg-mdiff foo 012345567ABCD # sha1 for "foo" as integrated upstream # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. usage() { echo "Usage: [-o ] [-O ] $(basename "$0") ..[]| ..[]|" exit 1 } diffopts= subdiffopts= while [ "$#" -gt 0 ]; do case "$1" in -o) diffopts="$2"; shift ;; -O) subdiffopts="-O $2"; shift ;; -*) usage ;; *) break ;; esac shift done if [ "$#" != 2 ]; then usage fi if [ -z "$diffopts" ]; then diffopts="-u" fi case "$1" in *..*) cmd1="stg diff $subdiffopts -r" ;; *) cmd1="stg show $subdiffopts" ;; esac case "$2" in *..*) cmd2="stg diff $subdiffopts -r" ;; *) cmd2="stg show $subdiffopts" ;; esac colordiff $diffopts \ -I '^index [0-9a-b]*..[0-9a-b]*' \ -I '^@@ .* @@' \ <($cmd1 "$1") <($cmd2 "$2") | less -RFX stgit-2.6.0/contrib/stg-show000077500000000000000000000010141520252120500160000ustar00rootroot00000000000000#!/bin/bash set -e # stg-show - unlike "stg show", just "git show" with knowledge of stg refs # Ex: # stg-show --color-words -- files # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. command=(git show) # substitute git id's for stg ones until -- while [ "$#" -gt 0 ]; do case "$1" in --) break ;; -*) command+=("$1"); shift ;; *) command+=( $(stg id "$1" 2>/dev/null || echo "$1") ); shift ;; esac done # append remaining args command+=("$@") eval "${command[@]}" stgit-2.6.0/contrib/stg-unnew000077500000000000000000000006441520252120500161640ustar00rootroot00000000000000#!/bin/sh set -e # stg-unnew - sort of "reverse an 'stg new'" # Remove the current patch from the stack, keeping its contents as # uncommitted changes. # CAVEAT: running this script on the bottom-most patch fails, since # "stg pick --fold" does not allow this situation. # Copyright (c) 2007 Yann Dirson # Subject to the GNU GPL, version 2. patch=$(stg top) stg pop --spill stg delete "$patch" stgit-2.6.0/contrib/stgbashprompt.sh000066400000000000000000000004671520252120500175430ustar00rootroot00000000000000# modify PS1 to your preference and include this file in your bashrc # or copy to /etc/bash_completions.d. if [ "$PS1" ]; then function __prompt_git() { local br top br=$(stg branch 2>/dev/null) || return top=$(stg top 2>/dev/null) || return echo "[$top@$br]" } PS1='\u@\h:$(__prompt_git)\W\$ ' fi stgit-2.6.0/contrib/stgit.el000066400000000000000000003543361520252120500157750ustar00rootroot00000000000000;;; stgit.el --- major mode for StGit interaction -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2007-2013 David Kågedal ;; ;; Author: David Kågedal ;; Homepage: http://stacked-git.github.io ;; Version: 0.17.1 ;; ;; This file is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2, or (at your option) ;; any later version. ;; ;; This file is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program. If not, see . ;;; Commentary: ;; ;; This is an interactive tool to interact with git branches using ;; StGit. ;; ;; StGit is a command-line tool providing similar functionality to ;; Quilt (i.e. pushing/popping patches to/from a stack) on top of Git. ;; These operations are performed using Git commands and the patches ;; are stored as Git commit objects, allowing easy merging of the ;; StGit patches into other repositories using standard Git ;; functionality. ;; ;; To start using the Emacs interface, run M-x stgit and select the ;; git repository you are working in. ;; ;; To get quick help about the available keybindings in the buffer, ;; press '?' ;;; Installation: ;; ;; To install: put this file on the load-path and place the following ;; in your .emacs file: ;; ;; (require 'stgit) ;; ;; To start: `M-x stgit' ;;; Code: (when (< emacs-major-version 22) (error "Emacs older than 22 is not supported by stgit.el")) (require 'git nil t) (require 'cl-lib) (require 'comint) (require 'dired) (require 'ewoc) (require 'easymenu) (require 'format-spec) (require 'vc) (defvar log-edit-parent-buffer) (defvar-local stgit-marked-patches nil "List of marked patches.") (defvar-local stgit-index-node nil) (defvar-local stgit-worktree-node nil) (defvar-local stgit-expanded-patches '(:work :index)) (defvar-local stgit-svn-find-rev-hash nil) (defvar-local stgit-ewoc nil) (defvar-local stgit-edit-patchsym nil) (defvar-local stgit-refresh-after-new nil) (defvar-local stgit-refresh-after-new nil) (defvar-local stgit-sink-to nil) (defvar-local stgit-patchsyms nil) (defvar-local old-process-sentinel nil) (defvar-local stgit-buffer nil) (defun stgit-set-default (symbol value) "Set default value of SYMBOL to VALUE and reload StGit buffers." (set-default symbol value) (dolist (buf (buffer-list)) (with-current-buffer buf (when (derived-mode-p 'stgit-mode) (stgit-post-refresh buf :reload))))) (defgroup stgit nil "A user interface for the StGit patch maintenance tool." :group 'tools :link '(function-link stgit) :link '(url-link "http://stacked-git.github.io")) (defcustom stgit-default-show-worktree t "Set to non-nil to by default show the working tree in a new stgit buffer. Use \\\\[stgit-toggle-worktree] to toggle this \ setting in an already-started StGit buffer." :type 'boolean :group 'stgit :link '(variable-link stgit-show-worktree)) (defvar-local stgit-show-worktree stgit-default-show-worktree) (defcustom stgit-default-show-unknown nil "Set to non-nil to by default show unknown files a new stgit buffer. Use \\\\[stgit-toggle-unknown] to toggle this \ setting in an already-started StGit buffer." :type 'boolean :group 'stgit :link '(variable-link stgit-show-unknown)) (defvar-local stgit-show-unknown stgit-default-show-unknown) (defcustom stgit-default-show-ignored nil "Set to non-nil to by default show ignored files a new stgit buffer. Use \\\\[stgit-toggle-ignored] to toggle this \ setting in an already-started StGit buffer." :type 'boolean :group 'stgit :link '(variable-link stgit-show-ignored)) (defvar-local stgit-show-ignored stgit-default-show-ignored) (defcustom stgit-default-show-patch-names t "If non-nil, default to showing patch names in a new stgit buffer. Use \\\\[stgit-toggle-patch-names] \ to toggle the this setting in an already-started StGit buffer." :type 'boolean :group 'stgit :link '(variable-link stgit-show-patch-names)) (defvar-local stgit-show-patch-names stgit-default-show-patch-names) (defcustom stgit-default-show-committed nil "Set to nil to inhibit showing of historical git commits by default. Use \\\\[stgit-toggle-committed] \ to toggle this setting and to control how many commits are shown." :type 'boolean :group 'stgit :link '(variable-link stgit-default-committed-count) :link '(variable-link stgit-show-committed)) (defvar-local stgit-show-committed stgit-default-show-committed) (defcustom stgit-default-committed-count 5 "The number of historical commits to show when `stgit-show-committed' is enabled." :type 'number :group 'stgit :link '(variable-link stgit-default-show-committed) :link '(variable-link stgit-committed-count)) (defvar-local stgit-committed-count stgit-default-committed-count) (defcustom stgit-default-show-svn t "Set to non-nil to by default show subversion information in a new stgit buffer. Use \\\\[stgit-toggle-svn] to toggle this \ setting in an already-started StGit buffer." :type 'boolean :group 'stgit :link '(variable-link stgit-show-worktree)) (defvar-local stgit-show-svn stgit-default-show-svn) (defcustom stgit-abbreviate-copies-and-renames t "If non-nil, abbreviate copies and renames. For example: \"dir/{old -> new}/file\" instead of \"dir/old/file -> dir/new/file\"." :type 'boolean :group 'stgit :set 'stgit-set-default) (defcustom stgit-find-copies-harder nil "Try harder to find copied files when listing patches. When not nil, runs git diff-tree with the --find-copies-harder flag, which reduces performance." :type 'boolean :group 'stgit :set 'stgit-set-default) (defcustom stgit-show-worktree-mode 'center "Where the \"Index\" and \"Work tree\" will be shown in the buffer. It can be set to \='top (above all patches), \='center (show between applied and unapplied patches), and \='bottom (below all patches)." :type '(radio (const :tag "above all patches (top)" top) (const :tag "between applied and unapplied patches (center)" center) (const :tag "below all patches (bottom)" bottom)) :group 'stgit :link '(variable-link stgit-show-worktree) :set 'stgit-set-default) (defcustom stgit-patch-line-format "%s%m%-30n %e%d" "The format string used to format patch lines. The format string is passed to `format-spec' and the following format characters are recognized: %s - A '+', '-', '>' or space, depending on whether the patch is applied, unapplied, top, or something else. %m - An asterisk if the patch is marked, and a space otherwise. %n - The patch name. %e - The string \"(empty) \" if the patch is empty. %d - The short patch description. %D - The short patch description, or the patch name. When `stgit-show-patch-names' is non-nil, the `stgit-noname-patch-line-format' variable is used instead." :type 'string :group 'stgit :set 'stgit-set-default) (defcustom stgit-noname-patch-line-format "%s%m%e%D" "The alternate format string used to format patch lines. It has the same semantics as `stgit-patch-line-format', and the display can be toggled between the two formats using \ \\\\[stgit-toggle-patch-names]. The alternate form is used when the patch name is hidden." :type 'string :group 'stgit :set 'stgit-set-default) (defcustom stgit-file-line-format " %-11s %-2m %n %c" "The format string used to format file lines. The format string is passed to `format-spec' and the following format characters are recognized: %s - A string describing the status of the file. %m - Mode change information %n - The file name. %c - A description of file changes." :type 'string :group 'stgit :set 'stgit-set-default) (defcustom stgit-git-program "git" "The program used by `stgit-mode' to run git." :type 'string :group 'stgit) (defcustom stgit-stg-program "stg" "The program used by `stgit-mode' to run StGit." :type 'string :group 'stgit) (defgroup stgit-faces nil "Faces for `stgit-mode'." :group 'stgit) (defface stgit-branch-name-face '((t :inherit bold)) "The face used for the StGit branch name." :group 'stgit-faces) (defface stgit-top-patch-face '((((background dark)) (:weight bold :foreground "yellow")) (((background light)) (:weight bold :foreground "purple")) (t (:weight bold))) "The face used for the top patch names." :group 'stgit-faces) (defface stgit-applied-patch-face '((((background dark)) (:foreground "light yellow")) (((background light)) (:foreground "purple")) (t ())) "The face used for applied patch names." :group 'stgit-faces) (defface stgit-unapplied-patch-face '((((background dark)) (:foreground "gray80")) (((background light)) (:foreground "orchid")) (t ())) "The face used for unapplied patch names." :group 'stgit-faces) (defface stgit-committed-patch-face '((((background dark)) (:foreground "gray50")) (((background light)) (:foreground "gray50")) (t ())) "The face used for already committed patch names." :group 'stgit-faces) (defface stgit-description-face '((((background dark)) (:foreground "tan")) (((background light)) (:foreground "dark red"))) "The face used for StGit descriptions." :group 'stgit-faces) (defface stgit-index-work-tree-title-face '((((supports :slant italic)) :slant italic) (t :inherit bold)) "StGit mode face used for the \"Index\" and \"Work tree\" titles." :group 'stgit-faces) (defface stgit-unmerged-file-face '((((class color) (background light)) (:foreground "red" :bold t)) (((class color) (background dark)) (:foreground "red" :bold t))) "StGit mode face used for unmerged file status." :group 'stgit-faces) (defface stgit-unknown-file-face '((((class color) (background light)) (:foreground "goldenrod" :bold t)) (((class color) (background dark)) (:foreground "goldenrod" :bold t))) "StGit mode face used for unknown file status." :group 'stgit-faces) (defface stgit-ignored-file-face '((((class color) (background light)) (:foreground "grey60")) (((class color) (background dark)) (:foreground "grey40"))) "StGit mode face used for ignored files.") (defface stgit-file-permission-face '((((class color) (background light)) (:foreground "green" :bold t)) (((class color) (background dark)) (:foreground "green" :bold t))) "StGit mode face used for permission changes." :group 'stgit-faces) (defface stgit-modified-file-face '((((class color) (background light)) (:foreground "purple")) (((class color) (background dark)) (:foreground "salmon"))) "StGit mode face used for modified file status." :group 'stgit-faces) (defconst stgit-patch-status-face-alist '((applied . stgit-applied-patch-face) (top . stgit-top-patch-face) (unapplied . stgit-unapplied-patch-face) (committed . stgit-committed-patch-face) (index . stgit-index-work-tree-title-face) (work . stgit-index-work-tree-title-face)) "Alist of face to use for a given patch status.") (defun stgit (dir) "Manage StGit patches for the tree in DIR. See `stgit-mode' for commands available." (interactive "DDirectory: \n") (switch-to-stgit-buffer (git-get-top-dir dir)) (stgit-reload)) (defun stgit-assert-mode () "Signal an error if not in an StGit buffer." (cl-assert (derived-mode-p 'stgit-mode) nil "Not an StGit buffer")) (unless (fboundp 'git-get-top-dir) (defun git-get-top-dir (dir) "Retrieve the top-level directory of a git tree." (let ((cdup (with-output-to-string (with-current-buffer standard-output (cd dir) (unless (eq 0 (call-process stgit-git-program nil t nil "rev-parse" "--show-cdup")) (error "Cannot find top-level git tree for %s" dir)))))) (expand-file-name (concat (file-name-as-directory dir) (car (split-string cdup "\n"))))))) (defun stgit-refresh-git-status (&optional dir) "If it exists, refresh the `git-status' buffer for DIR or `default-directory'." (when (and (fboundp 'git-find-status-buffer) (fboundp 'git-refresh-status)) (let* ((top-dir (git-get-top-dir (or dir default-directory))) (git-status-buffer (and top-dir (git-find-status-buffer top-dir)))) (when git-status-buffer (with-current-buffer git-status-buffer (git-refresh-status)))))) (defun stgit-find-buffer (dir) "Return the buffer displaying StGit patches for DIR, or nil if none." (setq dir (file-truename (file-name-as-directory dir))) (let ((buffers (buffer-list))) (while (and buffers (not (with-current-buffer (car buffers) (and (eq major-mode 'stgit-mode) (string= (file-truename default-directory) dir))))) (setq buffers (cdr buffers))) (and buffers (car buffers)))) (defun switch-to-stgit-buffer (dir) "Switch to a (possibly new) buffer displaying StGit patches for DIR." (setq dir (file-name-as-directory dir)) (let ((buffer (stgit-find-buffer dir))) (switch-to-buffer (or buffer (create-stgit-buffer dir))))) (cl-defstruct (stgit-patch (:conc-name stgit-patch->)) status name desc empty files-ewoc) (defun stgit-patch-display-name (patch) (let ((name (stgit-patch->name patch))) (cl-case name (:index "Index") (:work "Work Tree") (t (symbol-name name))))) (defun stgit-insert-without-trailing-whitespace (text) "Insert TEXT in buffer using `insert', without trailing whitespace. A newline is appended." (insert (string-trim-right text " ") ?\n)) (defun stgit-line-format () "Return the current line format. Will be either `stgit-patch-line-format' or `stgit-noname-patch-line-format'." (if stgit-show-patch-names stgit-patch-line-format stgit-noname-patch-line-format)) (defun stgit-patch-pp (patch) (let* ((status (stgit-patch->status patch)) (start (point)) (name (stgit-patch->name patch)) (face (cdr (assq status stgit-patch-status-face-alist))) (fmt (stgit-line-format)) (spec (format-spec-make ?s (cl-case status (applied "+") (top ">") (unapplied "-") (t " ")) ?m (if (memq name stgit-marked-patches) "*" " ") ?n (propertize (stgit-patch-display-name patch) 'face face 'syntax-table (string-to-syntax "w")) ?e (if (stgit-patch->empty patch) "(empty) " "") ?d (propertize (or (stgit-patch->desc patch) "") 'face 'stgit-description-face) ?D (propertize (let ((desc (stgit-patch->desc patch))) (if (zerop (length desc)) (stgit-patch-display-name patch) desc)) 'face face))) (text (format-spec fmt spec))) (stgit-insert-without-trailing-whitespace text) (put-text-property start (point) 'entry-type 'patch) (when (memq name stgit-expanded-patches) (stgit-insert-patch-files patch)) (put-text-property start (point) 'patch-data patch))) (defun create-stgit-buffer (dir) "Create a buffer for showing StGit patches. Argument DIR is the repository path." (let ((buf (create-file-buffer (concat dir "*stgit*"))) (inhibit-read-only t)) (with-current-buffer buf (setq default-directory dir) (stgit-mode) (setq stgit-ewoc (ewoc-create #'stgit-patch-pp "Branch:\n\n" "--\n" t)) (setq buffer-read-only t)) buf)) (def-edebug-spec stgit-capture-output (form body)) (defmacro stgit-capture-output (name &rest body) "Capture StGit output from BODY in buffer NAME and display it. Returns the result of the last form in BODY." (declare (debug ([&or stringp null] body)) (indent 1)) `(let ((output-buf (get-buffer-create ,(or name "*StGit output*"))) (stgit-dir default-directory) (inhibit-read-only t)) (set-buffer-major-mode output-buf) (with-current-buffer output-buf (buffer-disable-undo) (erase-buffer) (setq default-directory stgit-dir) (setq buffer-read-only t)) (prog1 (let ((standard-output output-buf)) ,@body) (with-current-buffer output-buf (set-buffer-modified-p nil) (setq buffer-read-only t) (if (< (point-min) (point-max)) (display-buffer output-buf t)))))) (defun stgit-make-run-args (args) "Return a copy of ARGS with its elements converted to strings." (mapcar (lambda (x) ;; don't use (format "%s" ...) to limit type errors (cond ((stringp x) x) ((integerp x) (number-to-string x)) ((symbolp x) (symbol-name x)) (t (error "Bad element in stgit-make-run-args args: %S" x)))) args)) (defvar stgit-inhibit-messages nil "Set to non-nil to inhibit messages when running `stg' commands. See also `stgit-message'.") (defun stgit-message (format-spec &rest args) "Call `message' on the arguments unless `stgit-inhibit-messages' is non-nil. See `message` for a description of FORMAT-SPEC and ARGS." (unless stgit-inhibit-messages (apply 'message format-spec args))) (defmacro stgit-show-task-message (message &rest body) "Display \"MESSAGE...\" before executing BODY and then display \"MESSAGE...done\" when done. MESSAGE will only be evaluated if necessary and no message will be shown if MESSAGE is nil. If `stgit-inhibit-messages' is non-nil, messages are suppressed. See also `stgit-message'. If MESSAGE is non-nil, BODY will be executed with `stgit-inhibit-messages' set to t. Returns the return value of BODY." (declare (indent 1) (debug (form body))) (let ((msg (make-symbol "msg"))) `(let ((,msg (and (not stgit-inhibit-messages) ,message))) (when ,msg (message "%s..." ,msg)) (prog1 (let ((stgit-inhibit-messages (or ,msg stgit-inhibit-messages))) ,@body) (when ,msg (message "%s...done" ,msg)))))) (defun stgit-run (&rest args) (setq args (stgit-make-run-args args)) (stgit-show-task-message (mapconcat #'identity `("Running" ,stgit-stg-program ,@args) " ") (apply 'call-process stgit-stg-program nil standard-output nil args))) (defun stgit-run-silent (&rest args) (let ((stgit-inhibit-messages t)) (apply 'stgit-run args))) (defun stgit-run-git (&rest args) (setq args (stgit-make-run-args args)) (stgit-show-task-message (mapconcat #'identity `("Running" ,stgit-git-program ,@args) " ") (apply 'call-process stgit-git-program nil standard-output nil args))) (defun stgit-run-git-silent (&rest args) (let ((stgit-inhibit-messages t)) (apply 'stgit-run-git args))) (defun stgit-index-empty-p () "Returns non-nil if the index contains no changes from HEAD." (zerop (stgit-run-git-silent "diff-index" "--cached" "--quiet" "HEAD"))) (defun stgit-work-tree-empty-p () "Returns non-nil if the work tree contains no changes from index." (zerop (stgit-run-git-silent "diff-files" "--quiet"))) (defvar stgit-did-advise nil "Set to non-nil if appropriate (non-stgit) git functions have been advised to update the stgit status when necessary.") (defconst stgit-allowed-branch-name-re ;; Disallow control characters, space, del, and "/:@^{}~" in ;; "/"-separated parts; parts may not start with a period (.) "^[^\0- ./:@^{}~\177][^\0- /:@^{}~\177]*\ \\(/[^\0- ./:@^{}~\177][^\0- /:@^{}~\177]*\\)*$" "Regular expression that (new) branch names must match.") (defun stgit-refresh-index () (when stgit-index-node (ewoc-invalidate (car stgit-index-node) (cdr stgit-index-node)))) (defun stgit-refresh-worktree () (when stgit-worktree-node (ewoc-invalidate (car stgit-worktree-node) (cdr stgit-worktree-node)))) (defun stgit-run-series-insert-index (ewoc) (setq stgit-index-node (cons ewoc (ewoc-enter-last ewoc (make-stgit-patch :status 'index :name :index :desc nil :empty nil))) stgit-worktree-node (cons ewoc (ewoc-enter-last ewoc (make-stgit-patch :status 'work :name :work :desc nil :empty nil))))) (defun stgit-get-position (&optional position) "Return position information at POSITION or point that can be restored later. Point restoration is done by `stgit-restore-position'." (let ((point (point))) (and position (goto-char position)) (prog1 (list (stgit-patch-name-at-point) (let ((f (stgit-patched-file-at-point))) (and f (stgit-file->file f))) (line-number-at-pos) (current-column)) (goto-char point)))) (defun stgit-restore-position (state) "Move point to the position in STATE, as returned by `stgit-get-position'." (cl-destructuring-bind (patch file line column) state (unless (and patch (cl-case (stgit-goto-patch patch file) ((t) (move-to-column column) t) ((:patch) t))) (goto-char (point-min)) (forward-line (1- line)) (move-to-column (if patch (stgit-goal-column) column))))) (defun stgit-get-window-state () "Return the state of the buffer and its windows. Use `stgit-restore-window-state' to restore the state." (list (current-buffer) (mapcar (lambda (window) (cons window (stgit-get-position (window-point window)))) (get-buffer-window-list (current-buffer) t t)) (stgit-get-position (point)) (let ((mark (mark))) (and mark (stgit-get-position mark))) mark-active transient-mark-mode)) (defun stgit-restore-window-state (state) "Restore the state of the stgit buffer and windows in STATE. State information is obtained from `stgit-get-window-state'." (cl-destructuring-bind (buffer window-states buffer-state mark-state old-mark-active old-transient-mark-mode) state (with-current-buffer buffer (mapc (lambda (x) (let ((window (car x)) (state (cdr x))) (when (and (window-live-p window) (eq (window-buffer window) buffer)) (stgit-restore-position state) (set-window-point window (point))))) window-states) (let ((mark-point (when mark-state (stgit-restore-position mark-state) (point)))) (stgit-restore-position buffer-state) (if (and mark-point (null old-mark-active)) (set-marker (mark-marker) mark-point) (set-mark mark-point)) (setq mark-active old-mark-active transient-mark-mode old-transient-mark-mode))))) (defmacro stgit-save-excursion (&rest body) "Save point relative position; execute BODY; restore point." (declare (indent 0) (debug (body))) (let ((state (make-symbol "state"))) `(let ((,state (stgit-get-window-state)) deactivate-mark) ,@body (stgit-restore-window-state ,state)))) (defun stgit-svn-find-rev (sha1 hash) "Return the subversion revision corresponding to SHA1 as reported by git svn. Cached data is stored in HASH, which must have been created using (make-hash-table :test \='equal)." (let ((result (gethash sha1 hash t))) (when (eq result t) (let ((svn-rev (with-output-to-string (stgit-run-git-silent "svn" "find-rev" "--" sha1)))) (setq result (when (string-match "\\`[0-9]+" svn-rev) (string-to-number (match-string 0 svn-rev)))) (puthash sha1 result hash))) result)) (defun stgit-run-series (ewoc) (setq stgit-index-node nil stgit-worktree-node nil) (let (all-patchsyms base) (when (and stgit-show-committed (> stgit-committed-count 0) (setq base (condition-case nil (stgit-id "{base}") (error nil)))) (let* ((show-svn stgit-show-svn) (svn-hash stgit-svn-find-rev-hash) (nentries (format "-%s" stgit-committed-count))) (with-temp-buffer (let* ((standard-output (current-buffer)) (fmt (stgit-line-format)) (commit-abbrev (when (string-match "%-\\([0-9]+\\)n" fmt) (string-to-number (match-string 1 fmt)))) (exit-status (stgit-run-git-silent "--no-pager" "log" "--no-color" "--reverse" "--pretty=oneline" nentries base))) (goto-char (point-min)) (if (not (zerop exit-status)) (message "Failed to run git log") (while (not (eobp)) (unless (looking-at "\\([0-9a-f]+\\)\\(\\.\\.\\.\\)? \\(.*\\)") (error "Syntax error in output from git log")) (let* ((state 'committed) (name (match-string 1)) (desc (match-string 3)) (empty nil)) (when show-svn (let ((svn-rev (stgit-svn-find-rev name svn-hash))) (when svn-rev (setq desc (format "(r%s) %s" svn-rev desc))))) (and commit-abbrev (< commit-abbrev (length name)) (setq name (substring name 0 commit-abbrev))) (setq name (intern name)) (setq all-patchsyms (cons name all-patchsyms)) (ewoc-enter-last ewoc (make-stgit-patch :status state :name name :desc desc :empty empty))) (forward-line 1))))))) (let ((inserted-index (not stgit-show-worktree))) (with-temp-buffer (let* ((standard-output (current-buffer)) (exit-status (stgit-run-silent "series" "--description" "--empty"))) (goto-char (point-min)) (if (not (zerop exit-status)) (cond ((looking-at "stg series: \\(.*\\)") (setq inserted-index t) (ewoc-set-hf ewoc (car (ewoc-get-hf ewoc)) (substitute-command-keys "-- not initialized; run \\[stgit-init]"))) ((looking-at ".*") (error "Error running stg: %s" (match-string 0)))) (while (not (eobp)) (unless (looking-at "\\([*0 ]\\)\\([>+-]\\)\\( \\)\\([^ ]+\\) *[|#] ?\\(.*\\)") (error "Syntax error in output from stg series")) (let* ((state-str (match-string 2)) (state (cond ((string= state-str ">") 'top) ((string= state-str "+") 'applied) ((string= state-str "-") 'unapplied))) (name (intern (match-string 4))) (desc (match-string 5)) (empty (string= (match-string 1) "0"))) (unless inserted-index (when (or (eq stgit-show-worktree-mode 'top) (and (eq stgit-show-worktree-mode 'center) (eq state 'unapplied))) (setq inserted-index t) (stgit-run-series-insert-index ewoc))) (setq all-patchsyms (cons name all-patchsyms)) (ewoc-enter-last ewoc (make-stgit-patch :status state :name name :desc desc :empty empty))) (forward-line 1))))) (unless inserted-index (stgit-run-series-insert-index ewoc)) (setq stgit-marked-patches (cl-intersection stgit-marked-patches all-patchsyms))))) (defun stgit-current-branch () "Return the name of the current branch." (substring (with-output-to-string (stgit-run-silent "branch")) 0 -1)) (defun stgit-reload (&optional description) "Update the contents of the StGit buffer. If DESCRIPTION is non-nil, it is displayed as a status message during the operation." (interactive) (stgit-assert-mode) (stgit-show-task-message description (let ((inhibit-read-only t)) (stgit-save-excursion (ewoc-filter stgit-ewoc #'(lambda (_) nil)) (ewoc-set-hf stgit-ewoc (concat "Branch: " (propertize (stgit-current-branch) 'face 'stgit-branch-name-face) "\n\n") (if stgit-show-worktree "--" (propertize (substitute-command-keys "--\n\"\ \\[stgit-toggle-worktree]\" shows the working tree\n") 'face 'stgit-description-face))) (stgit-run-series stgit-ewoc)) (stgit-refresh-git-status)))) (defconst stgit-file-status-code-strings (mapcar (lambda (arg) (cons (car arg) (propertize (cadr arg) 'face (car (cddr arg))))) '((add "Added" stgit-modified-file-face) (copy "Copied" stgit-modified-file-face) (delete "Deleted" stgit-modified-file-face) (modify "Modified" stgit-modified-file-face) (rename "Renamed" stgit-modified-file-face) (mode-change "Mode change" stgit-modified-file-face) (unmerged "Unmerged" stgit-unmerged-file-face) (unknown "Unknown" stgit-unknown-file-face) (ignore "Ignored" stgit-ignored-file-face))) "Alist of code symbols to description strings.") (defun stgit-file-status-code-as-string (file) "Return stgit status code for FILE as a string." (let* ((code (assq (stgit-file->status file) stgit-file-status-code-strings)) (score (stgit-file->cr-score file))) (when code (if (and score (/= score 100)) (format "%s %s" (cdr code) (propertize (format "%d%%" score) 'face 'stgit-description-face)) (cdr code))))) (defun stgit-file-status-code (str &optional score) "Return stgit status code from git status string STR." (let ((code (assoc str '(("A" . add) ("C" . copy) ("D" . delete) ("I" . ignore) ("M" . modify) ("R" . rename) ("T" . mode-change) ("U" . unmerged) ("X" . unknown))))) (setq code (if code (cdr code) 'unknown)) (when (stringp score) (if (> (length score) 0) (setq score (string-to-number score)) (setq score nil))) (if score (cons code score) code))) (defconst stgit-file-type-strings '((#o100 . "file") (#o120 . "symlink") (#o160 . "subproject")) "Alist of names of file types.") (defun stgit-file-type-string (type) "Return string describing file type TYPE (the high bits of file permission). Cf. `stgit-file-type-strings' and `stgit-file-type-change-string'." (let ((type-str (assoc type stgit-file-type-strings))) (or (and type-str (cdr type-str)) (format "unknown type %o" type)))) (defun stgit-file-type-change-string (old-perm new-perm) "Return string describing file type change from OLD-PERM to NEW-PERM. Cf. `stgit-file-type-string'." (let ((old-type (lsh old-perm -9)) (new-type (lsh new-perm -9))) (cond ((= old-type new-type) "") ((zerop new-type) "") ((zerop old-type) (if (= new-type #o100) "" (format "(%s)" (stgit-file-type-string new-type)))) (t (format "(%s -> %s)" (stgit-file-type-string old-type) (stgit-file-type-string new-type)))))) (defun stgit-file-mode-change-string (old-perm new-perm) "Return string describing file mode change from OLD-PERM to NEW-PERM. Cf. `stgit-file-type-change-string'." (setq old-perm (logand old-perm #o777) new-perm (logand new-perm #o777)) (if (or (= old-perm new-perm) (zerop old-perm) (zerop new-perm)) "" (let* ((modified (logxor old-perm new-perm)) (not-x-modified (logand (logxor old-perm new-perm) #o666))) (cond ((zerop modified) "") ((and (zerop not-x-modified) (or (and (eq #o111 (logand old-perm #o111)) (propertize "-x" 'face 'stgit-file-permission-face)) (and (eq #o111 (logand new-perm #o111)) (propertize "+x" 'face 'stgit-file-permission-face))))) (t (concat (propertize (format "%o" old-perm) 'face 'stgit-file-permission-face) (propertize " -> " 'face 'stgit-description-face) (propertize (format "%o" new-perm) 'face 'stgit-file-permission-face))))))) (cl-defstruct (stgit-file (:conc-name stgit-file->)) old-perm new-perm copy-or-rename cr-score cr-from cr-to status file) (defun stgit-escape-file-name-p (name) "Return non-nil if NAME must be escaped." (save-match-data (string-match "[\t\n\"\\]" name))) (defun stgit-escape-file-name (name &optional no-quotes) "Escape NAME if necessary. If NO-QUOTES is non-nil, do not enclose the result in double quotes." (if (stgit-escape-file-name-p name) (concat (if no-quotes "" "\"") (mapconcat (lambda (c) (cl-case c (?\t "\\t") (?\n "\\n") (?\" "\\\"") (?\\ "\\\\") (t (char-to-string c)))) name "") (if no-quotes "" "\"")) name)) (defun stgit-describe-copy-or-rename (file) (let* ((arrow (concat " " (propertize "->" 'face 'stgit-description-face) " ")) (esc-from (stgit-file->cr-from file)) (esc-to (stgit-file->cr-to file)) (quote "") from to common-head common-tail) (when (or (stgit-escape-file-name-p esc-from) (stgit-escape-file-name-p esc-to)) (setq esc-from (stgit-escape-file-name esc-from t) esc-to (stgit-escape-file-name esc-to t) quote "\"")) (when stgit-abbreviate-copies-and-renames (setq from (split-string esc-from "/") to (split-string esc-to "/")) (while (and from to (cdr from) (cdr to) (string-equal (car from) (car to))) (setq common-head (cons (car from) common-head) from (cdr from) to (cdr to))) (setq common-head (nreverse common-head) from (nreverse from) to (nreverse to)) (while (and from to (cdr from) (cdr to) (string-equal (car from) (car to))) (setq common-tail (cons (car from) common-tail) from (cdr from) to (cdr to))) (setq from (nreverse from) to (nreverse to))) (if (or common-head common-tail) (concat quote (if common-head (mapconcat #'identity common-head "/") "") (if common-head "/" "") (propertize "{" 'face 'stgit-description-face) (mapconcat #'identity from "/") arrow (mapconcat #'identity to "/") (propertize "}" 'face 'stgit-description-face) (if common-tail "/" "") (if common-tail (mapconcat #'identity common-tail "/") "") quote) (concat quote esc-from arrow esc-to quote)))) (defun stgit-file-pp (file) (let ((start (point)) (spec (format-spec-make ?s (stgit-file-status-code-as-string file) ?m (stgit-file-mode-change-string (stgit-file->old-perm file) (stgit-file->new-perm file)) ?n (if (stgit-file->copy-or-rename file) (stgit-describe-copy-or-rename file) (stgit-escape-file-name (stgit-file->file file))) ?c (propertize (stgit-file-type-change-string (stgit-file->old-perm file) (stgit-file->new-perm file)) 'face 'stgit-description-face)))) (stgit-insert-without-trailing-whitespace (format-spec stgit-file-line-format spec)) (add-text-properties start (point) (list 'entry-type 'file 'file-data file)))) (defun stgit-find-copies-harder-diff-arg () "Return the flag to use with `git-diff'. Depends on the value of `stgit-find-copies-harder'." (if stgit-find-copies-harder "--find-copies-harder" "-C")) (defun stgit-insert-ls-files (args file-flag) (let ((start (point))) (apply 'stgit-run-git (append '("ls-files" "--exclude-standard" "-z") args)) (goto-char start) (while (looking-at "\\([^\0]*\\)\0") (let ((name-len (- (match-end 0) (match-beginning 0)))) (insert ":0 0 0000000000000000000000000000000000000000 0000000000000000000000000000000000000000 " file-flag "\0") (forward-char name-len))))) (defun stgit-process-files (patch callback) (goto-char (point-min)) (when (looking-at "[0-9A-Fa-f]\\{40\\}\0") (goto-char (match-end 0))) (while (looking-at ":\\([0-7]+\\) \\([0-7]+\\) [0-9A-Fa-f]\\{40\\} [0-9A-Fa-f]\\{40\\} ") (let ((old-perm (string-to-number (match-string 1) 8)) (new-perm (string-to-number (match-string 2) 8))) (goto-char (match-end 0)) (let ((file (cond ((looking-at "\\([CR]\\)\\([0-9]*\\)\0\\([^\0]*\\)\0\\([^\0]*\\)\0") (let* ((patch-status (stgit-patch->status patch)) (file-subexp (if (eq patch-status 'unapplied) 3 4)) (file (match-string file-subexp))) (make-stgit-file :old-perm old-perm :new-perm new-perm :copy-or-rename t :cr-score (string-to-number (match-string 2)) :cr-from (match-string 3) :cr-to (match-string 4) :status (stgit-file-status-code (match-string 1)) :file file))) ((looking-at "\\([ABD-QS-Z]\\)\0\\([^\0]*\\)\0") (make-stgit-file :old-perm old-perm :new-perm new-perm :copy-or-rename nil :cr-score nil :cr-from nil :cr-to nil :status (stgit-file-status-code (match-string 1)) :file (match-string 2)))))) (goto-char (match-end 0)) (funcall callback file))))) (defun stgit-insert-patch-files (patch) "Expand (show modification of) the patch PATCH after the line at point." (let* ((patchsym (stgit-patch->name patch)) (end (point-marker)) (args (list "-z" (stgit-find-copies-harder-diff-arg))) (ewoc (ewoc-create #'stgit-file-pp nil nil t)) (show-ignored stgit-show-ignored) (show-unknown stgit-show-unknown)) (set-marker-insertion-type end t) (setf (stgit-patch->files-ewoc patch) ewoc) (with-temp-buffer (let ((standard-output (current-buffer))) (apply 'stgit-run-git (cond ((eq patchsym :work) (let (standard-output) (stgit-run-git "update-index" "--refresh")) `("diff-files" "-0" ,@args)) ((eq patchsym :index) `("diff-index" ,@args "--cached" "HEAD")) (t `("diff-tree" ,@args "-r" ,(stgit-id patchsym))))) (when (and (eq patchsym :work)) (when show-ignored (stgit-insert-ls-files '("--ignored" "--others") "I")) (when show-unknown (stgit-insert-ls-files '("--directory" "--no-empty-directory" "--others") "X")) (sort-regexp-fields nil ":[^\0]*\0\\([^\0]*\\)\0" "\\1" (point-min) (point-max))) (stgit-process-files patch (lambda (file) (ewoc-enter-last ewoc file))) (unless (ewoc-nth ewoc 0) (ewoc-set-hf ewoc "" (concat " " (propertize "" 'face 'stgit-description-face) "\n"))))) (goto-char end))) (defun stgit-find-file-revision (file patchsym &optional other-window) (let ((filename (expand-file-name (concat (file-name-nondirectory file) ".~" (symbol-name patchsym) "~") (file-name-directory file)))) (let ((coding-system-for-read 'no-conversion) (coding-system-for-write 'no-conversion)) (with-temp-file filename (unless (zerop (stgit-run-git-silent "cat-file" "blob" (concat (if (eq patchsym :index) "" (stgit-id patchsym)) ":" file))) (error "Command 'git cat-file' failed")))) (funcall (if other-window 'switch-to-buffer-other-window 'switch-to-buffer) (find-file-noselect filename)) (setq vc-parent-buffer filename))) (defun stgit-find-file (&optional other-window this-rev) (let* ((file (or (stgit-patched-file-at-point) (error "No file at point"))) (filename (expand-file-name (stgit-file->file file))) (patchsym (stgit-patch-name-at-point))) (if (and this-rev (not (eq patchsym :work))) (stgit-find-file-revision (stgit-file->file file) (stgit-patch-name-at-point) other-window) (unless (file-exists-p filename) (error "File does not exist")) (funcall (if other-window 'find-file-other-window 'find-file) filename) (when (eq (stgit-file->status file) 'unmerged) (smerge-mode 1))))) (defun stgit-expand (&optional patches collapse) "Show the contents of marked patches, or the patch at point. See also `stgit-collapse'. Non-interactively, operate on PATCHES, and collapse instead of expand if COLLAPSE is not nil." (interactive (list (stgit-patches-marked-or-at-point t))) (stgit-assert-mode) (let ((patches-diff (funcall (if collapse #'cl-intersection #'cl-set-difference) patches stgit-expanded-patches))) (setq stgit-expanded-patches (if collapse (cl-set-difference stgit-expanded-patches patches-diff) (append stgit-expanded-patches patches-diff))) (stgit-show-task-message (concat (if collapse "Collapsing" "Expanding") " " (if (= 1 (length patches-diff)) "patch" "patches")) (ewoc-map #'(lambda (patch) (memq (stgit-patch->name patch) patches-diff)) stgit-ewoc))) (move-to-column (stgit-goal-column))) (defun stgit-collapse (&optional patches) "Hide the contents of marked PATCHES, or the patch at point. See also `stgit-expand'." (interactive (list (stgit-patches-marked-or-at-point t))) (stgit-assert-mode) (stgit-expand patches t)) (defun stgit-select-patch () (let ((patchname (stgit-patch-name-at-point))) (stgit-expand (list patchname) (memq patchname stgit-expanded-patches)))) (defun stgit-expand-directory (file) (let* ((patch (stgit-patch-at-point)) (ewoc (stgit-patch->files-ewoc patch)) (node (ewoc-locate ewoc)) (filename (stgit-file->file file)) (start (make-marker)) (end (make-marker))) (save-excursion (forward-line 1) (set-marker start (point)) (set-marker end (point)) (set-marker-insertion-type end t)) (cl-assert (string-match "/$" filename)) ;; remove trailing "/" (setf (stgit-file->file file) (substring filename 0 -1)) (ewoc-invalidate ewoc node) (with-temp-buffer (let ((standard-output (current-buffer))) (stgit-insert-ls-files (list "--directory" "--others" "--no-empty-directory" "--" filename) "X") (stgit-process-files patch (lambda (f) (setq node (ewoc-enter-after ewoc node f)))))) (move-to-column (stgit-goal-column)) (let ((inhibit-read-only t)) (put-text-property start end 'patch-data patch)))) (defun stgit-select-file () (let* ((file (or (stgit-patched-file-at-point) (error "No file at point"))) (filename (stgit-file->file file))) (if (string-match "/$" filename) (stgit-expand-directory file) (stgit-find-file)))) (defun stgit-select () "With point on a patch, toggle showing files in the patch. With point on a file, open the associated file. Opens the target file for (applied) copies and renames." (interactive) (stgit-assert-mode) (cl-case (get-text-property (point) 'entry-type) (patch (stgit-select-patch)) (file (stgit-select-file)) (t (error "No patch or file on line")))) (defun stgit-find-file-other-window (&optional revision) "Open file at point in other window. With prefix argument, open a buffer with that REVISION of the file." (interactive "p") (stgit-assert-mode) (stgit-find-file t (> revision 1))) (defun stgit-find-file-merge () "Open file at point and merge it using `smerge-ediff'." (interactive) (stgit-assert-mode) (stgit-find-file t) (let ((filename (file-name-nondirectory buffer-file-name))) (smerge-ediff (concat "*" filename " GIT*") (concat "*" filename " PATCH*")))) (defun stgit-quit () "Hide the stgit buffer." (interactive) (stgit-assert-mode) (bury-buffer)) (defun stgit-git-status () "Show status using `git-status'." (interactive) (stgit-assert-mode) (unless (fboundp 'git-status) (error "The stgit-git-status command requires git-status")) (let ((dir default-directory)) (save-selected-window (pop-to-buffer nil) (git-status dir)))) (defun stgit-goal-column () "Return goal column for the current line." (cl-case (get-text-property (point) 'entry-type) (patch 2) (file 4) (t 0))) (defun stgit-next-line (&optional arg) "Move cursor vertically down ARG lines." (interactive "p") (stgit-assert-mode) (forward-line arg) (move-to-column (stgit-goal-column))) (defun stgit-previous-line (&optional arg) "Move cursor vertically up ARG lines." (interactive "p") (stgit-assert-mode) (forward-line (- arg)) (move-to-column (stgit-goal-column))) (defun stgit-next-patch (&optional arg) "Move cursor down ARG patches." (interactive "p") (stgit-assert-mode) (unless arg (setq arg 1)) (cond ((< arg 0) (stgit-previous-patch (- arg))) ((zerop arg) (move-to-column (stgit-goal-column))) (t (when (stgit-at-header-p) (ewoc-goto-node stgit-ewoc (ewoc-nth stgit-ewoc 0)) (setq arg (1- arg))) (ewoc-goto-next stgit-ewoc arg) (move-to-column goal-column)))) (defun stgit-previous-patch (&optional arg) "Move cursor up ARG patches." (interactive "p") (stgit-assert-mode) (unless arg (setq arg 1)) (cond ((< arg 0) (stgit-next-patch (- arg))) ((zerop arg) (move-to-column (stgit-goal-column))) ((stgit-at-header-p) (goto-char (point-min))) (t (let ((patch (stgit-patch-at-point))) (when (stgit-patched-file-at-point) (setq arg (1- arg))) (ewoc-goto-prev stgit-ewoc arg) (unless (zerop arg) (when (eq patch (stgit-patch-at-point)) (goto-char (point-min))))) (move-to-column (stgit-goal-column))))) (defun stgit-previous-patch-group (&optional arg) "Move to the previous group of patches. If ARG is non-nil, do this ARG times. If ARG is negative, move -ARG groups forward instead; cf. `stgit-next-patch-group'." (interactive "p") (stgit-assert-mode) (if (< arg 0) (stgit-previous-patch-group (- arg)) (while (and (not (bobp)) (> arg 0)) (stgit-previous-patch 1) (let* ((point (point)) (patch (stgit-patch-at-point)) (status (and patch (stgit-patch->status patch)))) (while (and (not (bobp)) (let* ((npatch (stgit-patch-at-point)) (nstatus (and npatch (stgit-patch->status npatch)))) (eq status nstatus))) (setq point (point)) (stgit-previous-patch 1)) (goto-char point)) (setq arg (1- arg))))) (defun stgit-next-patch-group (&optional arg) "Move to the next group of patches. If ARG is non-nil, do this ARG times. If ARG is negative, move -ARG groups backwards instead; cf. `stgit-previous-patch-group'." (interactive "p") (stgit-assert-mode) (if (< arg 0) (stgit-previous-patch-group (- arg)) (while (and (not (eobp)) (> arg 0)) (let* ((patch (stgit-patch-at-point)) (status (and patch (stgit-patch->status patch)))) (while (and (not (eobp)) (let* ((npatch (stgit-patch-at-point)) (nstatus (and npatch (stgit-patch->status npatch)))) (eq status nstatus))) (stgit-next-patch 1))) (setq arg (1- arg))))) (defvar stgit-mode-hook nil "Run after `stgit-mode' is setup.") (defvar stgit-mode-map nil "Keymap for StGit major mode.") (unless stgit-mode-map (let ((diff-map (make-sparse-keymap)) (toggle-map (make-sparse-keymap))) (mapc (lambda (arg) (define-key diff-map (car arg) (cdr arg))) '(("b" . stgit-diff-base) ("c" . stgit-diff-combined) ("m" . stgit-find-file-merge) ("o" . stgit-diff-ours) ("r" . stgit-diff-range) ("t" . stgit-diff-theirs))) (mapc (lambda (arg) (define-key toggle-map (car arg) (cdr arg))) '(("n" . stgit-toggle-patch-names) ("t" . stgit-toggle-worktree) ("h" . stgit-toggle-committed) ("i" . stgit-toggle-ignored) ("u" . stgit-toggle-unknown) ("s" . stgit-toggle-svn))) (setq stgit-mode-map (make-keymap)) (suppress-keymap stgit-mode-map) (mapc (lambda (arg) (define-key stgit-mode-map (car arg) (cdr arg))) `((" " . stgit-mark-down) ("m" . stgit-mark-down) ("\d" . stgit-unmark-up) ("u" . stgit-unmark-down) ("?" . stgit-help) ("h" . stgit-help) ("\C-p" . stgit-previous-line) ("\C-n" . stgit-next-line) ([up] . stgit-previous-line) ([down] . stgit-next-line) ("p" . stgit-previous-patch) ("n" . stgit-next-patch) ("\M-{" . stgit-previous-patch-group) ("\M-}" . stgit-next-patch-group) ([(control up)] . stgit-previous-patch-group) ([(control down)] . stgit-next-patch-group) ("s" . stgit-git-status) ("g" . stgit-reload-or-repair) ("r" . stgit-refresh) ("\C-c\C-r" . stgit-rename) ("e" . stgit-edit) ("M" . stgit-move-patches) ("S" . stgit-squash) ("N" . stgit-new) ("c" . stgit-new-and-refresh) ("\C-c\C-c" . stgit-commit) ("\C-c\C-u" . stgit-uncommit) ("U" . stgit-revert) ("R" . stgit-resolve-file) ("\r" . stgit-select) ("+" . stgit-expand) ("-" . stgit-collapse) ("o" . stgit-find-file-other-window) ("\C-o" . stgit-new-here) ([insertline] . stgit-new-here) ("i" . stgit-toggle-index) (">" . stgit-push-next) ("<" . stgit-pop-next) ("P" . stgit-push-or-pop) ("G" . stgit-goto) ("=" . stgit-diff) ("D" . stgit-delete) ([?\C-/] . stgit-undo) ("\C-_" . stgit-undo) ([?\C-c ?\C-/] . stgit-redo) ("\C-c\C-_" . stgit-redo) ("B" . stgit-branch) ("\C-c\C-b" . stgit-rebase) ("t" . ,toggle-map) ("d" . ,diff-map) ("q" . stgit-quit) ("!" . stgit-execute)))) (let ((at-unmerged-file '(let ((file (stgit-patched-file-at-point))) (and file (eq (stgit-file->status file) 'unmerged)))) (patch-collapsed-p '(lambda (p) (not (memq p stgit-expanded-patches))))) (easy-menu-define stgit-menu stgit-mode-map "StGit Menu" `("StGit" ["Reload" stgit-reload-or-repair :help "Reload StGit status from disk"] ["Repair" stgit-repair :keys "\\[universal-argument] \\[stgit-reload-or-repair]" :help "Repair StGit metadata"] "-" ["Undo" stgit-undo t] ["Redo" stgit-redo t] "-" ["Git status" stgit-git-status :active (fboundp 'git-status)] "-" ["New patch" stgit-new-and-refresh :help "Create a new patch from changes in index or work tree" :active (not (and (stgit-index-empty-p) (stgit-work-tree-empty-p)))] ["New empty patch" stgit-new :help "Create a new, empty patch"] ["(Un)mark patch" stgit-toggle-mark :label (if (memq (stgit-patch-name-at-point nil t) stgit-marked-patches) "Unmark patch" "Mark patch") :active (stgit-patch-name-at-point nil t)] ["Expand/collapse patch" (let ((patches (stgit-patches-marked-or-at-point))) (if (member-if ,patch-collapsed-p patches) (stgit-expand patches) (stgit-collapse patches))) :label (if (member-if ,patch-collapsed-p (stgit-patches-marked-or-at-point)) "Expand patches" "Collapse patches") :active (stgit-patches-marked-or-at-point)] ["Edit patch" stgit-edit :help "Edit patch comment" :active (stgit-patch-name-at-point nil t)] ["Rename patch" stgit-rename :active (stgit-patch-name-at-point nil t)] ["Push/pop patch" stgit-push-or-pop :label (if (subsetp (stgit-patches-marked-or-at-point nil t) (stgit-applied-patchsyms t)) "Pop patches" "Push patches")] ["Delete patches" stgit-delete :active (stgit-patches-marked-or-at-point nil t)] "-" ["Move patches" stgit-move-patches :active stgit-marked-patches :help "Move marked patch(es) to point"] ["Squash patches" stgit-squash :active (> (length stgit-marked-patches) 1) :help "Merge marked patches into one"] "-" ["Refresh top patch" stgit-refresh :active (not (and (stgit-index-empty-p) (stgit-work-tree-empty-p))) :help "Refresh the top patch with changes in index or work tree"] ["Refresh this patch" (stgit-refresh t) :keys "\\[universal-argument] \\[stgit-refresh]" :help "Refresh marked patch with changes in index or work tree" :active (and (not (and (stgit-index-empty-p) (stgit-work-tree-empty-p))) (stgit-patch-name-at-point nil t))] "-" ["Find file" stgit-select :active (eq (get-text-property (point) 'entry-type) 'file)] ["Open file" stgit-find-file-other-window :active (eq (get-text-property (point) 'entry-type) 'file)] ["Toggle file index" stgit-toggle-index :active (and (eq (get-text-property (point) 'entry-type) 'file) (memq (stgit-patch-name-at-point) '(:work :index))) :label (if (eq (stgit-patch-name-at-point) :work) "Move change to index" "Move change to work tree")] "-" ["Show diff" stgit-diff :active (get-text-property (point) 'entry-type)] ["Show diff for range of applied patches" stgit-diff-range :active (= (length stgit-marked-patches) 1)] ("Merge" :active (stgit-git-index-unmerged-p) ["Combined diff" stgit-diff-combined :active (memq (stgit-patch-name-at-point nil nil) '(:work :index))] ["Diff against base" stgit-diff-base :help "Show diff against the common base" :active (memq (stgit-patch-name-at-point nil nil) '(:work :index))] ["Diff against ours" stgit-diff-ours :help "Show diff against our branch" :active (memq (stgit-patch-name-at-point nil nil) '(:work :index))] ["Diff against theirs" stgit-diff-theirs :help "Show diff against their branch" :active (memq (stgit-patch-name-at-point nil nil) '(:work :index))] "-" ["Interactive merge" stgit-find-file-merge :help "Interactively merge the file" :active ,at-unmerged-file] ["Resolve file" stgit-resolve-file :help "Mark file conflict as resolved" :active ,at-unmerged-file] ) "-" ["Show index & work tree" stgit-toggle-worktree :style toggle :selected stgit-show-worktree] ["Show unknown files" stgit-toggle-unknown :style toggle :selected stgit-show-unknown :active stgit-show-worktree] ["Show ignored files" stgit-toggle-ignored :style toggle :selected stgit-show-ignored :active stgit-show-worktree] ["Show patch names" stgit-toggle-patch-names :style toggle :selected stgit-show-patch-names] ["Show recent commits" stgit-toggle-committed :style toggle :selected stgit-show-committed] ["Show subversion info" stgit-toggle-svn :style toggle :selected stgit-show-svn] "-" ["Switch branches" stgit-branch t :help "Switch to or create another branch"] ["Rebase branch" stgit-rebase t :help "Rebase the current branch"] "-" ["Customize StGit" (customize-group 'stgit)] )))) ;; disable tool bar editing buttons (put 'stgit-mode 'mode-class 'special) (defun stgit-mode () "Major mode for interacting with StGit. Start StGit using \\[stgit]. Basic commands: \\\ \\[stgit-help] Show this help text \\[stgit-quit] Hide the StGit buffer \\[describe-bindings] Show all key bindings \\[stgit-reload-or-repair] Reload the StGit buffer \\[universal-argument] \\[stgit-reload-or-repair] Repair StGit metadata \\[stgit-undo] Undo most recent StGit operation \\[stgit-redo] Undo recent undo \\[stgit-git-status] Run `git-status' (if available) \\[stgit-execute] Run an stg shell command Movement commands: \\[stgit-previous-line] Move to previous line \\[stgit-next-line] Move to next line \\[stgit-previous-patch] Move to previous patch \\[stgit-next-patch] Move to next patch \\[stgit-previous-patch-group] Move to previous patch group \\[stgit-next-patch-group] Move to next patch group \\[stgit-mark-down] Mark patch and move down \\[stgit-unmark-up] Unmark patch and move up \\[stgit-unmark-down] Unmark patch and move down Commands for patches: \\[stgit-select] Toggle showing changed files in patch \\[stgit-refresh] Refresh patch with changes in index or work tree \\[stgit-diff] Show the patch log and diff \\[stgit-expand] Show changes in marked patches \\[stgit-collapse] Hide changes in marked patches \\[stgit-new-and-refresh] Create a new patch from index or work tree \\[stgit-new] Create a new, empty patch \\[stgit-new-here] Create a new, empty patch before patch at point \\[stgit-rename] Rename patch \\[stgit-edit] Edit patch description \\[stgit-delete] Delete patch(es) \\[stgit-revert] Revert all changes in index or work tree \\[stgit-toggle-index] Toggle all changes between index and work tree \\[stgit-push-next] Push next patch onto stack \\[stgit-pop-next] Pop current patch from stack \\[stgit-push-or-pop] Push or pop marked patches \\[stgit-goto] Make patch at point current by popping or pushing \\[stgit-squash] Squash (meld together) patches \\[stgit-move-patches] Move marked patches to point \\[stgit-commit] Commit patch(es) \\[stgit-uncommit] Uncommit patch(es) Commands for files: \\[stgit-select] Open the file in this window \\[stgit-find-file-other-window] Open the file in another window \\[stgit-diff] Show the file's diff \\[stgit-toggle-index] Toggle change between index and work tree \\[stgit-revert] Revert changes to file Display commands: \\[stgit-toggle-patch-names] Toggle showing patch names \\[stgit-toggle-worktree] Toggle showing index and work tree \\[stgit-toggle-unknown] Toggle showing unknown files \\[stgit-toggle-ignored] Toggle showing ignored files \\[stgit-toggle-committed] Toggle showing recent commits \\[stgit-toggle-svn] Toggle showing subversion information Commands for diffs: \\[stgit-diff] Show diff of patch or file \\[stgit-diff-range] Show diff for range of patches \\[stgit-diff-base] Show diff against the merge base \\[stgit-diff-ours] Show diff against our branch \\[stgit-diff-theirs] Show diff against their branch With one prefix argument (e.g., \\[universal-argument] \\[stgit-diff]), \ ignore space changes. With two prefix arguments (e.g., \\[universal-argument] \ \\[universal-argument] \\[stgit-diff]), ignore all space changes. Commands for merge conflicts: \\[stgit-find-file-merge] Resolve conflicts using `smerge-ediff' \\[stgit-resolve-file] Mark unmerged file as resolved Commands for branches: \\[stgit-branch] Switch to or create another branch \\[stgit-rebase] Rebase the current branch Customization variables: `stgit-abbreviate-copies-and-renames' `stgit-default-show-ignored' `stgit-default-show-patch-names' `stgit-default-show-unknown' `stgit-default-show-worktree' `stgit-default-show-committed' `stgit-default-show-svn' `stgit-default-committed-count' `stgit-find-copies-harder' `stgit-show-worktree-mode' See also \\[customize-group] for the \"stgit\" group." (kill-all-local-variables) (buffer-disable-undo) (setq mode-name "StGit" major-mode 'stgit-mode goal-column 2) (use-local-map stgit-mode-map) (setq list-buffers-directory default-directory) (setq-local parse-sexp-lookup-properties t) (setq stgit-svn-find-rev-hash (make-hash-table :test 'equal)) (setq stgit-committed-count stgit-default-committed-count) (setq stgit-show-committed stgit-default-show-committed) (setq stgit-show-ignored stgit-default-show-ignored) (setq stgit-show-patch-names stgit-default-show-patch-names) (setq stgit-show-svn stgit-default-show-svn) (setq stgit-show-unknown stgit-default-show-unknown) (setq stgit-show-worktree stgit-default-show-worktree) (set-variable 'truncate-lines 't) (add-hook 'after-save-hook 'stgit-update-stgit-for-buffer) (unless stgit-did-advise (stgit-advise) (setq stgit-did-advise t)) (run-hooks 'stgit-mode-hook)) (defun stgit-update-stgit-advice (&rest _ignore) "Update work tree and index of stgit buffers. Intended to be used to advise other functions." (stgit-update-stgit-for-buffer :index)) (defun stgit-advise-funlist (funlist) "Advise functions in FUNLIST to refresh stgit buffers." (mapc (lambda (sym) (when (fboundp sym) (advice-add sym :after #'stgit-update-stgit-advice))) funlist)) (defun stgit-advise () "Advise appropriate (non-stgit) git functions to refresh stgit buffers." (with-eval-after-load "vc-git" (stgit-advise-funlist '(vc-git-rename-file vc-git-revert vc-git-register))) (with-eval-after-load "git" (stgit-advise-funlist '(git-add-file git-checkout git-revert-file git-remove-file))) (with-eval-after-load "dired" (stgit-advise-funlist '(dired-delete-file)))) (defvar stgit-pending-refresh-buffers nil "Alist of (`buffer' . `mode') of buffers that need to be refreshed. See `stgit-post-refresh' for the different values of `mode'.") (defun stgit-run-pending-refreshs () "Run all pending stgit buffer updates as posted by `stgit-post-refresh'." (let ((buffers stgit-pending-refresh-buffers) (stgit-inhibit-messages t)) (setq stgit-pending-refresh-buffers nil) (while buffers (let* ((elem (car buffers)) (buffer (car elem)) (mode (cdr elem))) (when (buffer-name buffer) (with-current-buffer buffer (stgit-save-excursion (if (eq mode :reload) (stgit-reload) (stgit-refresh-worktree) (when (eq mode :index) (stgit-refresh-index))))))) (setq buffers (cdr buffers))))) (defun stgit-post-refresh (buffer mode) "Update status in BUFFER when Emacs becomes idle. MODE specifies what to do: :work only update work tree :index update work tree and index :reload reload the entire buffer" (unless (memq mode '(:work :index :reload)) (error "Illegal refresh mode in stgit-post-refresh")) (unless stgit-pending-refresh-buffers (run-with-idle-timer 0.1 nil 'stgit-run-pending-refreshs)) (let ((elem (assq buffer stgit-pending-refresh-buffers))) (if elem ;; if buffer is already present, update its mode if necessary (let ((mode (cdr elem))) (when (cl-case mode (:index (eq mode :work)) (:reload t)) (setcdr elem mode))) ;; new entry (setq stgit-pending-refresh-buffers (cons (cons buffer mode) stgit-pending-refresh-buffers))))) (defun stgit-update-stgit-for-buffer (&optional mode) "When Emacs becomes idle, update the status in any `stgit-mode' buffers. MODE specifies how to update the buffer. See `stgit-post-refresh' for the different values MODE can have." (let* ((dir (cond ((derived-mode-p 'stgit-mode 'stgit-status-mode 'dired-mode) default-directory) (buffer-file-name (file-name-directory (expand-file-name buffer-file-name))))) (gitdir (and dir (condition-case nil (git-get-top-dir dir) (error nil)))) (buffer (and gitdir (stgit-find-buffer gitdir)))) (when buffer (stgit-post-refresh buffer (or mode :work))))) (defun stgit-add-mark (patchsym) "Mark the patch PATCHSYM." (setq stgit-marked-patches (cons patchsym stgit-marked-patches))) (defun stgit-remove-mark (patchsym) "Unmark the patch PATCHSYM." (setq stgit-marked-patches (delq patchsym stgit-marked-patches))) (defun stgit-clear-marks () "Unmark all patches." (setq stgit-marked-patches '())) (defun stgit-patch-at-point (&optional cause-error) "Return patch at point. If CAUSE-ERROR then throw an error when there is no patch." (let ((return (get-text-property (point) 'patch-data))) (when (and cause-error (not return)) (error "No patch at point")) return)) (defun stgit-patch-name-at-point (&optional cause-error types) "Return the patch name on the current line as a symbol. If CAUSE-ERROR is not nil, signal an error if none found. TYPES controls which types of commits and patches can be returned. If it is t, only allow stgit patches; if \='allow-committed, also allow historical commits; if nil, also allow work tree and index." (let ((patch (stgit-patch-at-point))) (and patch (memq (stgit-patch->status patch) (cl-case types ((nil) nil) ((allow-committed) '(work index)) ((t) '(work index committed)) (t (error "Bad value")))) (setq patch nil)) (cond (patch (stgit-patch->name patch)) (cause-error (error "No patch on this line"))))) (defun stgit-patched-file-at-point () (get-text-property (point) 'file-data)) (defun stgit-patches-marked-or-at-point (&optional cause-error types) "Return the symbols of the marked patches, or the patch on the current line. If CAUSE-ERROR is not nil, signal an error if none found. TYPES controls which types of commits and patches can be returned. If it is t, only allow stgit patches; if \='allow-committed, also allow historical commits; if nil, also allow work tree and index." (if stgit-marked-patches stgit-marked-patches (let ((patch (stgit-patch-name-at-point nil types))) (cond (patch (list patch)) (cause-error (error "No patches marked or at this line")) (t nil))))) (defun stgit-goto-patch (patchsym &optional file) "Move point to the line containing patch PATCHSYM and return t. If that patch cannot be found, do nothing and return nil. If the patch was found and FILE is not nil, instead move to that file's line and return t. If FILE cannot be found, stay on the line of PATCHSYM and return :patch." (let ((node (ewoc-nth stgit-ewoc 0)) result) (while (and node (not (eq (stgit-patch->name (ewoc-data node)) patchsym))) (setq node (ewoc-next stgit-ewoc node))) (cond ((and node file) (let* ((file-ewoc (stgit-patch->files-ewoc (ewoc-data node))) (file-node (ewoc-nth file-ewoc 0))) (while (and file-node (not (equal (stgit-file->file (ewoc-data file-node)) file))) (setq file-node (ewoc-next file-ewoc file-node))) (if file-node (progn (ewoc-goto-node file-ewoc file-node) (setq result t)) (ewoc-goto-node stgit-ewoc node) (setq result :patch)))) (node (ewoc-goto-node stgit-ewoc node) (setq result t))) (when result (move-to-column (stgit-goal-column))) result)) (defun stgit-init () "Run stg init to initialize the current branch for use with StGit." (interactive) (stgit-assert-mode) (unless (zerop (stgit-capture-output nil (stgit-run "init"))) (error "Command 'stg init' failed")) (stgit-reload)) (defun stgit-toggle-mark () "Toggle mark on the patch under point." (interactive) (stgit-assert-mode) (if (memq (stgit-patch-name-at-point t t) stgit-marked-patches) (stgit-unmark) (stgit-mark))) (defun stgit-mark () "Mark the patch under point." (interactive) (stgit-assert-mode) (let* ((node (ewoc-locate stgit-ewoc)) (patch (ewoc-data node))) (cl-case (stgit-patch->status patch) (work (error "Cannot mark the work tree")) (index (error "Cannot mark the index")) (committed (error "Cannot mark a committed patch"))) (stgit-add-mark (stgit-patch->name patch)) (let ((column (current-column))) (ewoc-invalidate stgit-ewoc node) (move-to-column column)))) (defun stgit-mark-down () "Mark the patch under point and move to the next patch." (interactive) (stgit-mark) (stgit-next-patch)) (defun stgit-unmark () "Remove mark from the patch on the current line." (interactive) (stgit-assert-mode) (let* ((node (ewoc-locate stgit-ewoc)) (patch (ewoc-data node))) (stgit-remove-mark (stgit-patch->name patch)) (let ((column (current-column))) (ewoc-invalidate stgit-ewoc node) (move-to-column column)))) (defun stgit-unmark-up () "Remove mark from the patch on the previous line." (interactive) (stgit-assert-mode) (stgit-previous-patch) (stgit-unmark)) (defun stgit-unmark-down () "Remove mark from the patch on the current line." (interactive) (stgit-assert-mode) (stgit-unmark) (stgit-next-patch)) (defun stgit-rename (name) "Rename the patch under point to NAME." (interactive (list (read-string "Patch name: " (symbol-name (stgit-patch-name-at-point t t))))) (stgit-assert-mode) (let ((old-patchsym (stgit-patch-name-at-point t t))) (unless (string-equal (symbol-name old-patchsym) name) (stgit-capture-output nil (stgit-run "rename" "--" old-patchsym name)) (let ((name-sym (intern name))) (when (memq old-patchsym stgit-expanded-patches) (setq stgit-expanded-patches (cons name-sym (delq old-patchsym stgit-expanded-patches)))) (when (memq old-patchsym stgit-marked-patches) (setq stgit-marked-patches (cons name-sym (delq old-patchsym stgit-marked-patches)))) (stgit-reload) (stgit-goto-patch name-sym))))) (defun stgit-reload-or-repair (repair) "Update the contents of the StGit buffer (`stgit-reload'). With a prefix argument, REPAIR the StGit metadata if the branch was modified with git commands (`stgit-repair')." (interactive "P") (stgit-assert-mode) (if repair (stgit-repair) (stgit-reload))) (defun stgit-repair () "Run stg repair." (interactive) (stgit-assert-mode) (stgit-capture-output nil (stgit-run "repair")) (stgit-reload)) (defun stgit-available-branches (&optional all skip-current) "Returns a list of the names of the available stg branches as strings. If ALL is not nil, also return non-stgit branches. If SKIP-CURRENT is not nil, do not include the current branch." (let ((output (with-output-to-string (stgit-run "branch" "--list"))) (pattern (format "^%c\\s-+%c\\s-+\\(\\S-+\\)" (if skip-current ?\ ?.) (if all ?. ?s))) (start 0) result) (while (string-match pattern output start) (setq result (cons (match-string 1 output) result)) (setq start (match-end 0))) result)) (defun stgit-branch (branch) "Switch to or create branch BRANCH." (interactive (list (completing-read "Switch to branch: " (stgit-available-branches nil t)))) (stgit-assert-mode) (when (equal branch (stgit-current-branch)) (error "Branch is already current")) (let ((merge (not (and (stgit-index-empty-p) (stgit-work-tree-empty-p))))) (when (cond ((and merge (not (yes-or-no-p "Attempt to merge uncommitted changes? "))) nil) ((member branch (stgit-available-branches t)) (stgit-capture-output nil (apply 'stgit-run (append '("branch") (and merge '("--merge")) '("--") (list branch)))) t) ((not (string-match stgit-allowed-branch-name-re branch)) (error "Invalid branch name")) (merge (error "Cannot merge changes into a new branch")) ((yes-or-no-p (format "Create branch \"%s\"? " branch)) (let ((branch-point (completing-read "Branch from (default current branch): " (stgit-available-branches)))) (stgit-capture-output nil (apply 'stgit-run `("branch" "--create" "--" ,branch ,@(unless (zerop (length branch-point)) (list branch-point))))) t))) ;; Do not expand any (normal) patches in the new branch (setq stgit-expanded-patches (cl-remove-if-not (lambda (p) (memq p '(:work :index))) stgit-expanded-patches)) (stgit-reload)))) (defun stgit-available-refs (&optional omit-stgit) "Returns a list of the available git refs. If OMIT-STGIT is not nil, filter out \"resf/heads/*.stgit\"." (let* ((output (with-output-to-string (stgit-run-git-silent "for-each-ref" "--format=%(refname)" "refs/tags" "refs/heads" "refs/remotes"))) (result (split-string output "\n" t))) (mapcar (lambda (s) (if (string-match "^refs/\\(heads\\|tags\\|remotes\\)/" s) (substring s (match-end 0)) s)) (if omit-stgit (cl-delete-if (lambda (s) (string-match "^refs/heads/.*\\.stgit$" s)) result) result)))) (defun stgit-parent-branch () "Return the parent branch of the current stg branch. It is determed as per git-config setting branch..stgit.parentbranch." (let ((output (with-output-to-string (stgit-run-git-silent "config" (format "branch.%s.stgit.parentbranch" (stgit-current-branch)))))) (when (string-match ".*" output) (match-string 0 output)))) (defun stgit-rebase (new-base) "Rebase the current branch to NEW-BASE. Interactively, first ask which branch to rebase to. Defaults to what git-config branch..stgit.parentbranch is set to." (interactive (list (completing-read "Rebase to: " (stgit-available-refs t) nil nil (stgit-parent-branch)))) (stgit-assert-mode) (stgit-capture-output nil (stgit-run "rebase" "--" new-base)) (stgit-reload)) (defun stgit-commit (count) "Run stg commit on (at most) COUNT commits. Interactively, the prefix argument is used as COUNT. A negative COUNT will uncommit using `stgit-uncommit' instead." (interactive "p") (stgit-assert-mode) (if (< count 0) (stgit-uncommit (- count)) (setq count (min count (length (stgit-applied-patches t)))) (stgit-capture-output nil (stgit-run "commit" "-n" count)) (stgit-reload))) (defun stgit-uncommit (count) "Run stg uncommit on COUNT commits. Interactively, the prefix argument is used as COUNT. A negative COUNT will commit using `stgit-commit' instead." (interactive "p") (stgit-assert-mode) (if (< count 0) (stgit-commit (- count)) (stgit-capture-output nil (stgit-run "uncommit" "-n" count)) (stgit-reload))) (defun stgit-neighbour-file () "Return the file name of the file at point. It will be the file after point, or the previous file if point is at the last file within a patch." (let ((old-point (point)) neighbour-file) (and (zerop (forward-line 1)) (let ((f (stgit-patched-file-at-point))) (and f (setq neighbour-file (stgit-file->file f))))) (goto-char old-point) (unless neighbour-file (and (zerop (forward-line -1)) (let ((f (stgit-patched-file-at-point))) (and f (setq neighbour-file (stgit-file->file f))))) (goto-char old-point)) neighbour-file)) (defun stgit-unmerged-file-stages (file) "Returns list of merge stages that contain FILE, which must be an unmerged file. Stage 1, the common ancestor, is \='ancestor. Stage 2, HEAD, is \='head. Stage 3, MERGE_HEAD, is \='merge-head." (let ((output (with-output-to-string (stgit-run-git-silent "ls-files" "-u" "-z" "--" (stgit-file->file file)))) stages start) (while (string-match "\\([0-7]*\\) \\([0-9A-Fa-f]\\{40\\}\\) \\([1-3]\\)\t\\([^\0]*\\)\0" output start) (setq stages (cons (elt [ancestor head merge-head] (1- (string-to-number (match-string 3 output)))) stages) start (match-end 0))) stages)) (defun stgit-revert-file () "Revert the file at point, which must be in the index or the working tree." (interactive) (stgit-assert-mode) (let* ((patched-file (or (stgit-patched-file-at-point) (error "No file on the current line"))) (patch-name (stgit-patch-name-at-point)) (file-status (stgit-file->status patched-file)) (rm-file (cond ((stgit-file->copy-or-rename patched-file) (stgit-file->cr-to patched-file)) ((eq file-status 'add) (stgit-file->file patched-file)))) (co-file (cond ((eq file-status 'rename) (stgit-file->cr-from patched-file)) ((not (memq file-status '(copy add unknown))) (stgit-file->file patched-file)))) (next-file (stgit-neighbour-file)) (rm-disk-file (when (memq file-status '(ignore unknown)) (stgit-file->file patched-file))) add-file) (unless (memq patch-name '(:work :index)) (error "No index or working tree file on this line")) (when (eq file-status 'unmerged) (let ((stages (stgit-unmerged-file-stages patched-file))) (if (memq 'head stages) (setq add-file (stgit-file->file patched-file)) (setq rm-file (stgit-file->file patched-file) co-file nil)))) (when (yes-or-no-p (cond (rm-disk-file (format "Delete %s? " rm-disk-file)) ((and rm-file co-file) "Revert 2 files? ") (t (format "Revert %s? " (or rm-file co-file))))) (when rm-disk-file (dired-delete-file rm-disk-file dired-recursive-deletes)) (stgit-capture-output nil (when rm-file (stgit-run-git "rm" "-f" "-q" "--" rm-file)) (when add-file (stgit-run-git "add" "--" add-file)) (when co-file (let ((rev (when (or (eq file-status 'unmerged) (eq patch-name :index)) '("HEAD")))) (apply #'stgit-run-git "checkout" `(,@rev "--" ,co-file))))) (stgit-reload) (stgit-goto-patch patch-name next-file)))) (defun stgit-revert () "Revert the change at point. The change must be in the index, the work tree, or a single change in either." (interactive) (stgit-assert-mode) (let ((patched-file (stgit-patched-file-at-point))) (if patched-file (stgit-revert-file) (let* ((patch-name (or (stgit-patch-name-at-point) (error "No patch or file at point"))) (patch-desc (cl-case patch-name (:index "index") (:work "work tree") (t (error (substitute-command-keys "Use \\[stgit-delete] to delete a patch")))))) (when (if (eq patch-name :work) (stgit-work-tree-empty-p) (stgit-index-empty-p)) (error (format "There are no changes in the %s to revert" patch-desc))) (and (eq patch-name :index) (not (stgit-work-tree-empty-p)) (error "Cannot revert index as work tree contains unstaged changes")) (when (yes-or-no-p (format "Revert all changes in the %s? " patch-desc)) (if (eq patch-name :index) (stgit-run-git-silent "reset" "--hard" "-q") (stgit-run-git-silent "checkout" "--" ".")) (stgit-save-excursion (stgit-refresh-index) (stgit-refresh-worktree))))))) (defun stgit-resolve-file () "Resolve conflict in the file at point." (interactive) (stgit-assert-mode) (let* ((patched-file (stgit-patched-file-at-point)) (patch (stgit-patch-at-point)) (patch-name (and patch (stgit-patch->name patch))) (status (and patched-file (stgit-file->status patched-file)))) (unless (memq patch-name '(:work :index)) (error "No index or working tree file on this line")) (unless (eq status 'unmerged) (error "No conflict to resolve at the current line")) (stgit-capture-output nil (stgit-move-change-to-index (stgit-file->file patched-file))) (stgit-reload))) (defun stgit-push-or-pop-patches (do-push npatches) "Push (if DO-PUSH is not nil) or pop (if DO-PUSH is nil) NPATCHES patches, or all patches if NPATCHES is t." (stgit-assert-mode) (stgit-capture-output nil (apply 'stgit-run (if do-push "push" "pop") (if (eq npatches t) '("--all") (list "-n" npatches)))) (stgit-reload) (stgit-refresh-git-status)) (defun stgit-push-next (npatches) "Push the first unapplied patch. With numeric prefix argument, push that many patches." (interactive "p") (stgit-push-or-pop-patches t npatches)) (defun stgit-pop-next (npatches) "Pop the topmost applied patch. With numeric prefix argument, pop that many patches. If NPATCHES is t, pop all patches." (interactive "p") (stgit-push-or-pop-patches nil npatches)) (defun stgit-applied-patches (&optional only-patches) "Return a list of the applied patches. If ONLY-PATCHES is not nil, exclude index and work tree." (let ((states (if only-patches '(applied top) '(applied top index work))) result) (ewoc-map (lambda (patch) (when (memq (stgit-patch->status patch) states) (setq result (cons patch result))) nil) stgit-ewoc) result)) (defun stgit-applied-patchsyms (&optional only-patches) "Return a list of the symbols of the applied patches. If ONLY-PATCHES is not nil, exclude index and work tree." (mapcar #'stgit-patch->name (stgit-applied-patches only-patches))) (defun stgit-push-or-pop () "Push or pop the marked patches." (interactive) (stgit-assert-mode) (let* ((patchsyms (stgit-patches-marked-or-at-point t t)) (applied-syms (stgit-applied-patchsyms t)) (unapplied (cl-set-difference patchsyms applied-syms))) (stgit-capture-output nil (apply 'stgit-run (if unapplied "push" "pop") "--" (stgit-sort-patches (if unapplied unapplied patchsyms))))) (stgit-reload)) (defun stgit-at-header-p () "Return non-nil if point is in the header area above all patches." (not (previous-single-property-change (point) 'patch-data))) (defun stgit-at-footer-p () "Return non-nil if point is in the footer area below all patches." (not (next-single-property-change (point) 'patch-data))) (defun stgit-goto-target () "Return the goto target at point: a patchsym, :top, or :bottom." (let ((patch (stgit-patch-at-point))) (cond (patch (cl-case (stgit-patch->status patch) ((work index) nil) ((committed) :bottom) (t (stgit-patch->name patch)))) ((stgit-at-footer-p) :top) ((stgit-at-header-p) :bottom)))) (defun stgit-goto () "Go to the patch on the current line. Push or pop patches to make this patch topmost. Push or pop all patches if used on a line after or before all patches." (interactive) (stgit-assert-mode) (let ((patchsym (stgit-goto-target))) (unless patchsym (error "No patch to go to on this line")) (cl-case patchsym (:top (stgit-push-or-pop-patches t t)) (:bottom (stgit-push-or-pop-patches nil t)) (t (stgit-capture-output nil (stgit-run "goto" "--" patchsym)) (stgit-reload))))) (defun stgit-id (patchsym) "Return the git commit id for PATCHSYM. If PATCHSYM is a keyword, returns PATCHSYM unmodified." (if (keywordp patchsym) patchsym (let ((result (with-output-to-string (stgit-run-silent "id" "--" patchsym)))) (unless (string-match "^\\([0-9A-Fa-f]\\{40\\}\\)$" result) (error "Cannot find commit id for %s" patchsym)) (match-string 1 result)))) (defun stgit-whitespace-diff-arg (arg) (when (numberp arg) (cond ((> arg 4) "--ignore-all-space") ((> arg 1) "--ignore-space-change")))) (defun stgit-show-patch (unmerged-stage ignore-whitespace) "Show the patch on the current line. UNMERGED-STAGE is the argument to `git-diff' that that selects which stage to diff against in the case of unmerged files." (let* ((space-arg (stgit-whitespace-diff-arg ignore-whitespace)) (patch-name (stgit-patch-name-at-point t)) (entry-type (get-text-property (point) 'entry-type)) (diff-desc (cl-case entry-type (file "diff") (patch "patch") (t (error "No patch or file at point"))))) (stgit-show-task-message (concat "Showing " diff-desc) (stgit-capture-output (concat "*StGit " diff-desc "*") (cl-case entry-type (file (let* ((patched-file (stgit-patched-file-at-point)) (patch-id (let ((id (stgit-id patch-name))) (if (and (eq id :index) (eq (stgit-file->status patched-file) 'unmerged)) :work id))) (args (append (and space-arg (list space-arg)) (and (stgit-file->cr-from patched-file) (list (stgit-find-copies-harder-diff-arg))) (cond ((eq patch-id :index) '("--cached")) ((eq patch-id :work) (list unmerged-stage)) (t (list (concat patch-id "^") patch-id))) (and (eq (stgit-file->status patched-file) 'copy) '("--diff-filter=C")) (if (stgit-file->copy-or-rename patched-file) (list (stgit-file->cr-from patched-file) (stgit-file->cr-to patched-file)) (list (stgit-file->file patched-file)))))) (apply 'stgit-run-git "diff" args))) (patch (let* ((patch-id (stgit-id patch-name))) (if (or (eq patch-id :index) (eq patch-id :work)) (apply 'stgit-run-git "diff" (stgit-find-copies-harder-diff-arg) (append (and space-arg (list space-arg)) (if (eq patch-id :index) '("--cached") (list unmerged-stage)))) (let ((args (append '("show" "--color=never" "-O" "--patch-with-stat") `("-O" ,(stgit-find-copies-harder-diff-arg)) (and space-arg (list "-O" space-arg)) (list (stgit-patch-name-at-point))))) (apply 'stgit-run args)))))) (with-current-buffer standard-output (goto-char (point-min)) (diff-mode)))))) (defmacro stgit-define-diff (name diff-arg &optional unmerged-action) `(defun ,name (&optional ignore-whitespace) ,(format "Show the patch on the current line. %sWith a prefix argument, ignore whitespace. With a prefix argument greater than four (e.g., \\[universal-argument] \ \\[universal-argument] \\[%s]), ignore all whitespace." (if unmerged-action (format "For unmerged files, %s.\n\n" unmerged-action) "") name) (interactive "p") (stgit-assert-mode) (stgit-show-patch ,diff-arg ignore-whitespace))) (stgit-define-diff stgit-diff "--ours" nil) (stgit-define-diff stgit-diff-ours "--ours" "diff against our branch") (stgit-define-diff stgit-diff-theirs "--theirs" "diff against their branch") (stgit-define-diff stgit-diff-base "--base" "diff against the merge base") (stgit-define-diff stgit-diff-combined "--cc" "show a combined diff") (defun stgit-diff-range (&optional ignore-whitespace) "Show diff for the range of patches between point and the marked patch. With a prefix argument, ignore whitespace. With a prefix argument greater than four (e.g., \\[universal-argument] \ \\[universal-argument] \\[stgit-diff-range]), ignore all whitespace." (interactive "p") (stgit-assert-mode) (unless (= (length stgit-marked-patches) 1) (error "Need exactly one patch marked")) (let* ((patches (stgit-sort-patches (cons (stgit-patch-name-at-point t 'allow-committed) stgit-marked-patches) t)) (first-patch (car patches)) (second-patch (if (cdr patches) (cadr patches) first-patch)) (whitespace-arg (stgit-whitespace-diff-arg ignore-whitespace)) (applied (stgit-applied-patchsyms t))) (unless (and (memq first-patch applied) (memq second-patch applied)) (error "Can only show diff range for applied patches")) (stgit-capture-output (format "*StGit diff %s..%s*" first-patch second-patch) (apply 'stgit-run-git "diff" "--patch-with-stat" (stgit-find-copies-harder-diff-arg) (append (and whitespace-arg (list whitespace-arg)) (list (format "%s^" (stgit-id first-patch)) (stgit-id second-patch)))) (with-current-buffer standard-output (goto-char (point-min)) (diff-mode))))) (defun stgit-move-change-to-index (file &optional force) "Copies the work tree state of FILE to index, using git add or git rm. If FORCE is not nil, use --force." (let ((op (if (or (file-exists-p file) (file-symlink-p file)) '("add") '("rm" "-q")))) (stgit-capture-output "*git output*" (apply 'stgit-run-git (append op (and force '("--force")) '("--") (list file)))))) (defun stgit-remove-change-from-index (file) "Unstages the change in FILE from the index." (stgit-capture-output "*git output*" (stgit-run-git "reset" "-q" "--" file))) (defun stgit-git-index-unmerged-p () (let (result) (with-output-to-string (setq result (not (zerop (stgit-run-git-silent "diff-index" "--cached" "--diff-filter=U" "--quiet" "HEAD"))))) result)) (defun stgit-assert-no-unmerged-changes () "Signal an error if there are any unmerged changes in the index." (when (stgit-git-index-unmerged-p) (error (substitute-command-keys "Resolve unmerged changes with \\[stgit-resolve-file] first")))) (defun stgit-file-toggle-index () "Move modified file in or out of the index. Leaves the point where it is, but moves the mark to where the file ended up. You can then jump to the file with \ \\[exchange-point-and-mark]." (interactive) (stgit-assert-mode) (let* ((patched-file (or (stgit-patched-file-at-point) (error "No file on the current line"))) (patched-status (stgit-file->status patched-file))) (when (eq patched-status 'unmerged) (error (substitute-command-keys "Use \\[stgit-resolve-file] to move an unmerged file to the index"))) (let* ((patch (stgit-patch-at-point)) (patch-name (stgit-patch->name patch)) (mark-file (if (eq patched-status 'rename) (stgit-file->cr-to patched-file) (stgit-file->file patched-file))) (point-file (if (eq patched-status 'rename) (stgit-file->cr-from patched-file) (stgit-neighbour-file)))) (cond ((eq patch-name :work) (stgit-move-change-to-index (stgit-file->file patched-file) (eq patched-status 'ignore))) ((eq patch-name :index) (stgit-remove-change-from-index (stgit-file->file patched-file))) (t (error "Can only move files between working tree and index"))) (stgit-save-excursion (stgit-refresh-worktree) (stgit-refresh-index)) (stgit-goto-patch (if (eq patch-name :index) :work :index) mark-file) (push-mark nil t t) (setq deactivate-mark t) (stgit-goto-patch patch-name point-file)))) (defun stgit-toggle-index () "Move change in or out of the index. Works on index and work tree, as well as files in either. Leaves the point where it is, but moves the mark to where the file ended up. You can then jump to the file with \ \\[exchange-point-and-mark]." (interactive) (stgit-assert-mode) (if (stgit-patched-file-at-point) (stgit-file-toggle-index) (let ((patch-name (stgit-patch-name-at-point))) (unless (memq patch-name '(:index :work)) (error "Can only move changes between working tree and index")) (stgit-assert-no-unmerged-changes) (if (if (eq patch-name :index) (stgit-index-empty-p) (stgit-work-tree-empty-p)) (message "No changes to be moved") (stgit-capture-output nil (if (eq patch-name :work) (stgit-run-git "add" "--update") (stgit-run-git "reset" "--mixed" "-q"))) (stgit-save-excursion (stgit-refresh-worktree) (stgit-refresh-index))) (stgit-goto-patch patch-name) (push-mark nil t t) (setq deactivate-mark t) (stgit-goto-patch (if (eq patch-name :index) :work :index))))) (defun stgit-edit () "Edit the patch on the current line." (interactive) (stgit-assert-mode) (let ((patchsym (stgit-patch-name-at-point t t)) (edit-buf (get-buffer-create "*StGit edit*")) (dir default-directory)) (log-edit 'stgit-confirm-edit t nil edit-buf) (setq stgit-edit-patchsym patchsym) (setq default-directory dir) (let ((standard-output edit-buf)) (save-excursion (stgit-run-silent "edit" "--save-template=-" "--" patchsym))))) (defun stgit-confirm-edit () (interactive) (let ((file (make-temp-file "stgit-edit-")) (start (point-min)) (summary-string "Summary: ")) ;; log-edit puts this summary string here that we do not want (if (string-equal (buffer-substring start (+ 1 (length summary-string))) summary-string) (setq start (+ start (length summary-string)))) (write-region start (point-max) file) (stgit-capture-output nil (stgit-run "edit" "-f" file "--" stgit-edit-patchsym)) (with-current-buffer log-edit-parent-buffer (stgit-reload)))) (defun stgit-new-here (add-sign) "Create a new patch before the patch at point, asking for a commit message. With a prefix argument, include a \"Signed-off-by:\" line at the end of the patch description. This works like `stgit-new' followed by `stgit-move'." (interactive "P") (stgit-assert-mode) (let ((patch (stgit-patch-at-point t))) (cl-case (stgit-patch->status patch) ((index work) (stgit-new add-sign)) ((applied top) (unless (and (stgit-index-empty-p) (stgit-work-tree-empty-p)) (error "Index and worktree must not contain any changes")) (stgit-new add-sign nil (stgit-patch->name patch))) (t (error "Can only be used on applied patches"))))) (defun stgit-new (add-sign &optional refresh sink-to) "Create a new patch, asking for a commit message. With a prefix argument, include a \"Signed-off-by:\" line at the end of the message. If REFRESH is non-nil, also refresh the patch after creating it. If SINK-TO is non-nil, sink the created patch to the patch with that name (a symbol)." (interactive "P") (stgit-assert-mode) (let ((edit-buf (get-buffer-create "*StGit edit*")) (dir default-directory)) (log-edit 'stgit-confirm-new t nil edit-buf) (setq default-directory dir) (setq stgit-refresh-after-new refresh) (setq stgit-sink-to sink-to) (when add-sign (save-excursion (let ((standard-output (current-buffer))) (stgit-run-silent "new" "--sign" "--save-template=-")))))) (defun stgit-confirm-new () (interactive) (let ((file (make-temp-file "stgit-edit-")) (refresh stgit-refresh-after-new) new-patch) (write-region (point-min) (point-max) file) (stgit-capture-output nil (stgit-run "new" "-f" file)) (let ((top (with-output-to-string (stgit-run "top")))) (when (string-match "\\`\\(.+\\)" top) (setq new-patch (intern (match-string 1 top))))) (when stgit-sink-to (stgit-run "sink" "-t" stgit-sink-to)) (with-current-buffer log-edit-parent-buffer (if refresh (stgit-refresh) (stgit-reload)) (stgit-goto-patch new-patch)))) (defun stgit-new-and-refresh (add-sign) "Create a new patch based on the current changes, asking for a commit message. With a prefix argument, include a \"Signed-off-by:\" line at the end of the patch. This works just like running `stgit-new' followed by `stgit-refresh'." (interactive "P") (stgit-assert-mode) (stgit-assert-no-unmerged-changes) (stgit-new add-sign t)) (defun stgit-create-patch-name (description) "Create a patch name from a long DESCRIPTION." (let ((patch "")) (while (> (length description) 0) (cond ((string-match "\\`[a-zA-Z_-]+" description) (setq patch (downcase (concat patch (match-string 0 description)))) (setq description (substring description (match-end 0)))) ((string-match "\\` +" description) (setq patch (concat patch "-")) (setq description (substring description (match-end 0)))) ((string-match "\\`[^a-zA-Z_-]+" description) (setq description (substring description (match-end 0)))))) (cond ((= (length patch) 0) "patch") ((> (length patch) 20) (substring patch 0 20)) (t patch)))) (defun stgit-delete (patchsyms &optional spill-p) "Delete the patches in PATCHSYMS. Interactively, delete the marked patches, or the patch at point. With a prefix argument, or SPILL-P, spill the patch contents to the work tree and index." (interactive (list (stgit-patches-marked-or-at-point t t) current-prefix-arg)) (stgit-assert-mode) (unless patchsyms (error "No patches to delete")) (when (memq :index patchsyms) (error "Cannot delete the index")) (when (memq :work patchsyms) (error "Cannot delete the work tree")) (let ((npatches (length patchsyms))) (when (yes-or-no-p (format "Really delete %d patch%s%s? " npatches (if (= 1 npatches) "" "es") (if spill-p " (spilling contents to index)" ""))) (let ((args (append (when spill-p '("--spill")) '("--") patchsyms))) (stgit-capture-output nil (apply 'stgit-run "delete" args)) (stgit-reload))))) (defun stgit-move-patches-target () "Return the patchsym indicating a target patch for `stgit-move-patches'. This is either the first unmarked patch at or after point, or one of :top and :bottom if the point is after or before the applied patches." (save-excursion (let (result) (while (not result) (let ((patchsym (stgit-patch-name-at-point))) (cond ((memq patchsym '(:work :index)) (setq result :top)) (patchsym (if (memq patchsym stgit-marked-patches) (stgit-next-patch) (setq result patchsym))) ((re-search-backward "^>" nil t) (setq result :top)) (t (setq result :bottom))))) result))) (defun stgit-sort-patches (patchsyms &optional allow-duplicates) "Returns a list of patches in PATCHSYMS sorted by patch series position. The bottommost position is first. PATCHSYMS must not contain duplicate entries, unless ALLOW-DUPLICATES is not nil." (let (sorted-patchsyms) (ewoc-map #'(lambda (patch) (let ((name (stgit-patch->name patch))) (when (memq name patchsyms) (setq sorted-patchsyms (cons name sorted-patchsyms)))) nil) stgit-ewoc) (setq sorted-patchsyms (nreverse sorted-patchsyms)) (unless allow-duplicates (unless (= (length patchsyms) (length sorted-patchsyms)) (error "Internal error"))) sorted-patchsyms)) (defun stgit-move-patches (patchsyms target-patch) "Move the patches in PATCHSYMS to below TARGET-PATCH. If TARGET-PATCH is :bottom or :top, move the patches to the bottom or top of the stack, respectively. Interactively, move the marked patches to where the point is." (interactive (list stgit-marked-patches (stgit-move-patches-target))) (stgit-assert-mode) (unless patchsyms (error "Need at least one patch to move")) (unless target-patch (error "Point not at a patch")) ;; need to have patchsyms sorted by position in the stack (let ((sorted-patchsyms (stgit-sort-patches patchsyms))) (stgit-capture-output nil (if (eq target-patch :top) (apply 'stgit-run "float" "--" sorted-patchsyms) (apply 'stgit-run "sink" (append (unless (eq target-patch :bottom) (list "--to" target-patch)) '("--") sorted-patchsyms))))) (stgit-reload)) (defun stgit-squash (patchsyms) "Squash the patches in PATCHSYMS. Interactively, squash the marked patches. Unless there are any conflicts, the patches will be merged into one patch, which will occupy the same spot in the series as the deepest patch had before the squash." (interactive (list stgit-marked-patches)) (stgit-assert-mode) (when (< (length patchsyms) 2) (error "Need at least two patches to squash")) (let ((stgit-buffer (current-buffer)) (edit-buf (get-buffer-create "*StGit edit*")) (dir default-directory) (sorted-patchsyms (stgit-sort-patches patchsyms))) (log-edit 'stgit-confirm-squash t nil edit-buf) (setq stgit-patchsyms sorted-patchsyms) (setq default-directory dir) (let ((result (let ((standard-output edit-buf)) (save-excursion (apply 'stgit-run-silent "squash" "--save-template=-" "--" sorted-patchsyms))))) ;; stg squash may have reordered the patches or caused conflicts (with-current-buffer stgit-buffer (stgit-reload)) (unless (eq 0 result) (fundamental-mode) (rename-buffer "*StGit error*") (resize-temp-buffer-window) (switch-to-buffer-other-window stgit-buffer) (error "Command 'stg squash' failed"))))) (defun stgit-confirm-squash () (interactive) (let ((file (make-temp-file "stgit-edit-"))) (write-region (point-min) (point-max) file) (stgit-capture-output nil (apply 'stgit-run "squash" "-f" file "--" stgit-patchsyms)) (with-current-buffer log-edit-parent-buffer (stgit-clear-marks) ;; Go to first marked patch and stay there (goto-char (point-min)) (re-search-forward (concat "^[>+-]\\*") nil t) (move-to-column goal-column) (let ((pos (point))) (stgit-reload) (goto-char pos))))) (defun stgit-help () "Display help for the StGit mode." (interactive) (describe-function 'stgit-mode)) (defun stgit-execute-process-sentinel (process sentinel) (let (old-sentinel stgit-buf) (with-current-buffer (process-buffer process) (setq old-sentinel old-process-sentinel stgit-buf stgit-buffer)) (and (memq (process-status process) '(exit signal)) (buffer-live-p stgit-buf) (with-current-buffer stgit-buf (stgit-reload))) (funcall old-sentinel process sentinel))) (defun stgit-execute-process-filter (process output) (with-current-buffer (process-buffer process) (let* ((old-point (point)) (pmark (process-mark process)) (insert-at (marker-position pmark)) (at-pmark (= insert-at old-point))) (goto-char insert-at) (insert-before-markers output) (comint-carriage-motion insert-at (point)) (set-marker pmark (point)) (unless at-pmark (goto-char old-point))))) (defun stgit-execute (&optional git-mode) "Prompt for an stg command to execute in a shell. The names of any marked patches or the patch at point are inserted in the command to be executed. With a prefix argument, or if GIT-MODE is non-nil, insert SHA1 sums of the marked patches instead, and prompt for a git command. If the command ends in an ampersand, run it asynchronously. When the command has finished, reload the stgit buffer." (interactive "P") (stgit-assert-mode) (let* ((patches (stgit-sort-patches (stgit-patches-marked-or-at-point nil 'allow-committed))) (patch-names (mapcar 'symbol-name patches)) (hyphens (cl-find-if (lambda (s) (string-match "^-" s)) patch-names)) (program (if git-mode stgit-git-program stgit-stg-program)) (defaultcmd (concat program " " (and patch-names " ") (and hyphens patch-names "-- ") (mapconcat (if git-mode 'stgit-id 'identity) patch-names " "))) (cmd (read-from-minibuffer "Shell command: " (cons defaultcmd (+ (length program) 2)) nil nil 'shell-command-history)) (async (string-match "&[ \t]*\\'" cmd)) (buffer (get-buffer-create (if async "*Async Shell Command*" "*Shell Command Output*")))) ;; cannot use minibuffer as stgit-reload would overwrite it; if we ;; show the buffer, shell-command will not use the minibuffer (display-buffer buffer) (shell-command cmd) (if async (let ((old-buffer (current-buffer))) (with-current-buffer buffer (let ((process (get-buffer-process buffer))) (setq old-process-sentinel (process-sentinel process)) (setq stgit-buffer old-buffer) (set-process-filter process 'stgit-execute-process-filter) (set-process-sentinel process 'stgit-execute-process-sentinel)))) (with-current-buffer buffer (comint-carriage-motion (point-min) (point-max))) (shrink-window-if-larger-than-buffer (get-buffer-window buffer)) (stgit-reload)))) (defun stgit-undo-or-redo (redo hard) "Run stg undo or, if REDO is non-nil, stg redo. If HARD is non-nil, use the --hard flag." (stgit-assert-mode) (let ((cmd (if redo "redo" "undo"))) (stgit-capture-output nil (if hard (when (or (and (stgit-index-empty-p) (stgit-work-tree-empty-p)) (y-or-n-p (format "Hard %s may overwrite index/work tree changes. Continue? " cmd))) (stgit-run cmd "--hard")) (stgit-run cmd)))) (stgit-reload)) (defun stgit-undo (&optional arg) "Run stg undo. With prefix argument, run it with the --hard flag. See also `stgit-redo'." (interactive "P") (stgit-undo-or-redo nil arg)) (defun stgit-redo (&optional arg) "Run stg redo. With prefix argument, run it with the --hard flag. See also `stgit-undo'." (interactive "P") (stgit-undo-or-redo t arg)) (defun stgit-refresh (&optional arg) "Run stg refresh. If the index contains any changes, only refresh from index. With prefix argument, refresh the marked patch or the patch under point." (interactive "P") (stgit-assert-mode) (stgit-assert-no-unmerged-changes) (let ((patchargs (if arg (let ((patches (stgit-patches-marked-or-at-point t t))) (when (> (length patches) 1) (error "Too many patches marked")) (cons "-p" patches)) nil))) (unless (stgit-index-empty-p) (setq patchargs (cons "--index" patchargs))) (stgit-capture-output nil (apply 'stgit-run "refresh" patchargs)) (stgit-refresh-git-status)) (stgit-reload)) (defvar stgit-show-worktree nil "If nil, inhibit showing work tree and index in the stgit buffer. See also `stgit-show-worktree-mode'.") (defvar stgit-show-ignored nil "If nil, inhibit showing files ignored by git.") (defvar stgit-show-unknown nil "If nil, inhibit showing files not registered with git.") (defvar stgit-show-patch-names t "If nil, inhibit showing patch names.") (defvar stgit-show-committed nil "If nil, inhibit showing recent commits.") (defvar stgit-show-svn nil "If nil, inhibit showing git svn information.") (defvar stgit-committed-count nil "The number of recent commits to show.") (defmacro stgit-define-toggle-view (sym desc help) (declare (indent 1) (debug (symbolp stringp stringp))) (let* ((name (symbol-name sym)) (fun (intern (concat "stgit-toggle-" name))) (flag (intern (concat "stgit-show-" name)))) `(progn ;; make help-follow find the correct function (put (quote ,fun) 'definition-name 'stgit-define-toggle-view) (defun ,fun (&optional arg) ,help (interactive "P") (stgit-assert-mode) (setq ,flag (if arg (> (prefix-numeric-value arg) 0) (not ,flag))) (stgit-reload (concat (if ,flag "Showing" "Hiding") " " ,desc)))))) (stgit-define-toggle-view worktree "work tree and index" "Toggle the visibility of the work tree. With ARG, show the work tree if ARG is positive. Its initial setting is controlled by `stgit-default-show-worktree'. `stgit-show-worktree-mode' controls where on screen the index and work tree will show up.") (stgit-define-toggle-view ignored "ignored files" "Toggle the visibility of files ignored by git in the work tree. With ARG, show these files if ARG is positive. Its initial setting is controlled by `stgit-default-show-ignored'. Use \\[stgit-toggle-worktree] to show the work tree.") (stgit-define-toggle-view unknown "unknown files" "Toggle the visibility of files not registered with git in the work tree. With ARG, show these files if ARG is positive. Its initial setting is controlled by `stgit-default-show-unknown'. Use \\[stgit-toggle-worktree] to show the work tree.") (stgit-define-toggle-view patch-names "patch names" "Toggle the visibility of patch names. With ARG, show patch names if ARG is positive. The initial setting is controlled by `stgit-default-show-patch-names'.") (stgit-define-toggle-view svn "subversion revisions" "Toggle showing subversion information from git svn. With ARG, show svn information if ARG is positive. The initial setting is controlled by `stgit-default-show-svn'.") (defun stgit-toggle-committed (&optional arg) "Toggle the visibility of historical git commits. With ARG, set the number of commits to show to ARG, and disable them if ARG is zero. The initial setting is controlled by `stgit-default-show-committed'." (interactive "P") (stgit-assert-mode) (if (null arg) (setq stgit-show-committed (not stgit-show-committed)) (let ((n (prefix-numeric-value arg))) (setq stgit-show-committed (> n 0)) (setq stgit-committed-count n))) (stgit-reload (format "%s historical commits" (if (and stgit-show-committed (> stgit-committed-count 0)) "Showing" "Hiding")))) (provide 'stgit) ;;; stgit.el ends here stgit-2.6.0/contrib/vim/000077500000000000000000000000001520252120500150765ustar00rootroot00000000000000stgit-2.6.0/contrib/vim/Makefile000066400000000000000000000007641520252120500165450ustar00rootroot00000000000000prefix ?= $(HOME)/.local DESTDIR ?= INSTALL ?= install all: install: install-ftdetect install-syntax install-ftdetect: ftdetect/stg.vim $(INSTALL) -d $(DESTDIR)$(prefix)/share/vim/vimfiles/ftdetect $(INSTALL) -m 0644 $< $(DESTDIR)$(prefix)/share/vim/vimfiles/ftdetect install-syntax: syntax/*.vim $(INSTALL) -d $(DESTDIR)$(prefix)/share/vim/vimfiles/syntax $(INSTALL) -m 0644 $? $(DESTDIR)$(prefix)/share/vim/vimfiles/syntax clean: .PHONY: all clean install install-ftdetect install-syntax stgit-2.6.0/contrib/vim/README000066400000000000000000000005071520252120500157600ustar00rootroot00000000000000To syntax highlight StGit commit messages in vim: * For the current user only: > mkdir -p ~/.vim/ftdetect ~/.vim/syntax > cp syntax/*.vim ~/.vim/syntax/ > cp ftdetect/*.vim ~/.vim/ftdetect/ * For all users: # cp syntax/*.vim /usr/share/vim/site/syntax/ # cp ftdetect/*.vim /usr/share/vim/site/ftdetect/ stgit-2.6.0/contrib/vim/ftdetect/000077500000000000000000000000001520252120500167005ustar00rootroot00000000000000stgit-2.6.0/contrib/vim/ftdetect/stg.vim000066400000000000000000000035251520252120500202170ustar00rootroot00000000000000" Vim filetype detection plugin " Language: StGit commit messages " Author: Zane Bitter if has("autocmd") " Detect 'stg new' files autocmd BufNewFile,BufRead .stgit-new.txt setlocal filetype=stgnew autocmd BufNewFile,BufRead .stgitmsg.txt setlocal filetype=stgnew " Ignore the modeline so we get type 'stgnew' instead of 'diff' autocmd BufNewFile,BufRead .stgitmsg.txt setlocal nomodeline " Detect 'stg edit' files autocmd BufNewFile,BufRead .stgit-edit.txt setlocal filetype=stgedit autocmd BufNewFile,BufRead .stgit-edit.patch setlocal filetype=stgedit autocmd BufNewFile,BufRead .stgit-edit.diff setlocal filetype=stgedit autocmd BufNewFile,BufRead .stgit-failed.patch setlocal filetype=stgedit " Detect 'stg squash' files autocmd BufNewFile,BufRead .stgit-squash.txt setlocal filetype=stgsquash " Detect 'stg mail' files autocmd BufNewFile,BufRead .stgitmail.txt setlocal filetype=stgmail " A modeline in a diff belongs to the diffed file, so ignore it autocmd BufNewFile,BufRead .stgit-edit.patch setlocal nomodeline autocmd BufNewFile,BufRead .stgit-edit.diff setlocal nomodeline autocmd BufNewFile,BufRead .stgit-failed.patch setlocal nomodeline autocmd BufNewFile,BufRead .stgitmail.txt setlocal nomodeline " Set parameters on 'stg new' files to be consistent with the modeline autocmd FileType stgnew setlocal textwidth=75 autocmd FileType stgnew setlocal nobackup " For other stg files set textwidth the same as 'stg new' autocmd FileType stgedit setlocal textwidth=75 autocmd FileType stgmail setlocal textwidth=75 autocmd FileType stgsquash setlocal textwidth=75 endif " has("autocmd") stgit-2.6.0/contrib/vim/syntax/000077500000000000000000000000001520252120500164245ustar00rootroot00000000000000stgit-2.6.0/contrib/vim/syntax/stgedit.vim000066400000000000000000000026271520252120500206130ustar00rootroot00000000000000" Vim syntax file " Language: StGit 'stg edit' commit message file " Author: Zane Bitter if exists("b:current_syntax") finish endif syn include @stgDiff syntax/diff.vim syn case match syn sync minlines=50 if has("spell") syn spell toplevel endif syn region stgeditHeaders start="\%^\S\+:" end="^$" nextgroup=stgeditFirstLine skipempty contains=stgeditHeaderKey,stgeditEmailAddr syn match stgeditHeaderKey "^\S\+:" contained syn match stgeditEmailAddr "<.\{-}>" contained contains=@NoSpell syn match stgeditFirstLine "^.\+" contained nextgroup=stgeditDiffs,stgeditComment,stgeditBlank skipnl syn match stgeditSummary "^.\{0,50\}" contained containedin=stgeditFirstLine nextgroup=stgeditOverflow contains=@Spell syn match stgeditOverflow ".*" contained contains=@Spell syn match stgeditBlank "^.\+" contained contains=@Spell syn match stgeditComment "^#.*" syn region stgeditDiffs start="^# ---\+ >8 ---\+" end="%$" contains=@stgDiff fold syn region stgeditDiff start="^\%(diff --git \)\@=" end="^\%(diff --git \|$\)\@=" contained containedin=stgeditDiffs contains=@stgDiff fold hi def link stgeditHeaderKey Type hi def link stgeditEmailAddr Special hi def link stgeditSummary Keyword hi def link stgeditComment Comment hi def link stgeditBlank Error let b:current_syntax = "stgedit" stgit-2.6.0/contrib/vim/syntax/stgmail.vim000066400000000000000000000012461520252120500206040ustar00rootroot00000000000000" Vim syntax file " Language: StGit 'stg mail' file " Author: Zane Bitter if exists("b:current_syntax") finish endif runtime! syntax/mail.vim unlet b:current_syntax syn include @stgDiff syntax/diff.vim syn case match syn sync minlines=50 if has("spell") syn spell toplevel endif syn match stgmailComment "^#.*" syn region stgmailDiffs start="^---" end="%$" contains=@stgDiff fold syn region stgmailDiff start="^\%(diff --git \)\@=" end="^\%(diff --git \|$\)\@=" contained containedin=stgmailDiffs contains=@stgDiff fold hi def link stgmailComment Comment let b:current_syntax = "stgmail" stgit-2.6.0/contrib/vim/syntax/stgnew.vim000066400000000000000000000015621520252120500204540ustar00rootroot00000000000000" Vim syntax file " Language: StGit 'stg new' commit message file " Author: Zane Bitter if exists("b:current_syntax") finish endif syn case match syn sync minlines=50 if has("spell") syn spell toplevel endif syn match stgnewFirstLine "\%^.*" nextgroup=stgnewSTG,stgnewComment,stgnewBlank skipnl syn match stgnewSummary "^.\{0,50\}" contained containedin=stgnewFirstLine nextgroup=stgnewOverflow contains=@Spell syn match stgnewOverflow ".*" contained contains=@Spell syn match stgnewBlank "^.\+" contained contains=@Spell syn match stgnewSTG "^STG:.*" syn match stgnewComment "^#.*" hi def link stgnewSummary Keyword hi def link stgnewComment Comment hi def link stgnewSTG Comment hi def link stgnewBlank Error let b:current_syntax = "stgnew" stgit-2.6.0/contrib/vim/syntax/stgsquash.vim000066400000000000000000000026661520252120500211750ustar00rootroot00000000000000" Vim syntax file " Language: StGit 'stg squash' commit message file " Author: Zane Bitter if exists("b:current_syntax") finish endif syn case match syn sync minlines=50 if has("spell") syn spell toplevel endif syn match stgsqFirstLine "\%^.*" nextgroup=stgsqComment,stgsqContext,stgsqBlank skipnl syn match stgsqSummary "^.\{0,50\}" contained containedin=stgsqFirstLine nextgroup=stgsqOverflow contains=@Spell syn match stgsqOverflow ".*" contained contains=@Spell syn match stgsqBlank "^.\+" contained contains=@Spell syn match stgsqSeparator "-\+$" contained syn region stgsqPatch start="^\(.\{66\}-\{4\}$\)\@=" end="\(^.\{66\}-\{4\}$\)\@=" contained containedin=stgsqContext contains=@Spell fold syn match stgsqNextPatch "^.\{66\}-\{4\}$" contained containedin=stgsqPatch contains=stgsqPatchName syn match stgsqPatchName "^.\{-\}\(-*$\)\@=" contained containedin=stgsqNextPatch nextgroup=stgsqSeparator syn region stgsqContext start="^---" end="%$" contains=@Spell fold syn match stgsqComment "^#.*" hi def link stgsqSummary Keyword hi def link stgsqComment Comment hi def link stgsqBlank Error hi def link stgsqContext Comment hi def link stgsqPatch Constant hi def link stgsqPatchName Identifier hi def link stgsqSeparator Comment let b:current_syntax = "stgsquash" stgit-2.6.0/contrib/wix/000077500000000000000000000000001520252120500151125ustar00rootroot00000000000000stgit-2.6.0/contrib/wix/.gitignore000066400000000000000000000000351520252120500171000ustar00rootroot00000000000000/stgit-*.msi /stgit-*.wixpdb stgit-2.6.0/contrib/wix/Makefile000066400000000000000000000010641520252120500165530ustar00rootroot00000000000000CARGO ?= cargo --locked RM ?= rm -f STGIT_VERSION := $(shell $(CARGO) metadata --format-version=1 --no-deps | \ grep -Eo '"version":"[^"]+"' | \ sed -Ee 's/"version":"([^"]+)"/\1/g') msi: stgit.wxs release-build wix build -arch x64 -src $< -ext WixToolset.UI.wixext -out stgit-$(STGIT_VERSION).msi -define StGitVersion=$(STGIT_VERSION) -bindpath ..\.. release-build: $(MAKE) -C ../.. STG_PROFILE=release build completion .PHONY: release-build clean: $(RM) stgit-*.msi $(RM) stgit-*.wixpdb .PHONY: clean stgit-2.6.0/contrib/wix/README.md000066400000000000000000000010071520252120500163670ustar00rootroot00000000000000# StGit Windows MSI This directory contains files supporting the build of an MSI installer for Windows environments. The MSI is built using the [WiX Toolset](https://wixtoolset.org/) version 4.0.5. The WiX Toolset may be installed with the following command: ``` dotnet tool install --global wix --version 4.0.5 ``` The installer also requires the WixUI extension, which can be installed with: ``` wix extension add -g WixToolset.UI.wixext ``` To build the StGit msi installer, run: ``` make -C contrib/wix ``` stgit-2.6.0/contrib/wix/banner.bmp000066400000000000000000002476061520252120500170760ustar00rootroot00000000000000BMO6(:POٹU3;BB:^(=̻K'@L(P-P-P-P-K'>R/BBM*P-P-O,O,O,O,P-P-L)AH #o}<DN+P-P-O,M+K*N,N,K*M+O,P-P-M*C@}Zj:F !O,P-P-O,L+N+e9y!D|"F|"Fx!Db7L+L+O,P-P-N+E <hwsEW9H #O,P-P-O,L*P-h;|"Fz!Ex!Dx!Dx!Dx!Dz!E{!Ef:N,L*O,P-P-O,G "9~Sdd1E:I %O,P-O,N,K*S.l=}"Gz!Ex!Dx!Dx!Dw!Cw!Cx!Dx!Dx!Dz!E|"FjT1BBM*P-P-O,M+K*]4v C|"Fy!Dx!Dx!Dw Cu BsA%L+Z-\,Z,Z,Z,Z-\+Y$KsAu Bw Cx!Dx!Dy!D|"Ft A[3K*M+O,P-P-L)@H #$I %P-P-O,M+L*a6x!D{!Fx!Dx!Dx!Dw Ct Bu B&N,[,[,Z,Z,Z,Z,Z,Z,Z,Z-\,Z%MtAu Bw Cx!Dx!Dx!D{"Fw C^5K*M+O,P-P-J&#_+@=L*M+d8z!E{!Ex!Dx!Dx!Dw Ct Aw C'P-\,[,Z,Z,Z,Z,[-\-\,[,Z,Z,Z,Z,[,[&Ou Bt Bw Cx!Dx!Dx!D{!Ey!Db7L+L*?V5˹^/|!Fz!Ex!Dx!Dw Cv CsAy!E(R-\,[,Z,Z,Z,Z-\)V$J|"F|"F$K*W-\,Z,Z,Z,Z,[-\'Qw CtAw Cx!Dx!Dx!Dz!E{!E\.d|m 3y Dx!Dx!Dw Cv CsA|"F)T-\,[,Z,Z,Z,[-\)T|"FsAv Bv Cv Cv BrA~"G)U-\,Z,Z,Z,Z,[-\(Sz!EsAv Cw!Dx!Dx!Dy Do6qZq:w Cx!Dw Cv CrA#H*V-\,Z,Z,Z,Z,[-\(Ry!DsAv Cw!Cx!Dx!Dx!Dx!Dw Cv CsA{!F(S-\,[,Z,Z,Z,[-\)U~"GsAv Cw Cx!Dw Cp9\azf+q;u BsA$J+X-\,Z,Z,Z,Z,[,['Pv Ct Bw Cx!Dx!Dx!Dy!Dz!Ez!Ey!Dx!Dx!Dx!Dw CsAx!D'Q-\,[,Z,Z,Z,Z-\*W#IrAv Bre9f9o?|"Fy!Ex!Dx!Dx!Dw Ct Bv C&P,[,[,Z,Z,Z,Z-\+XCsԞ2_*Y,Z,Z,Z,Z-\+Z%LsAu Bw Cx!Dx!Dx!Dz!E|"Fg:O,K*M+M+K*Q-j<|"Fz!Ex!Dx!Dx!Dw Cu Bt B%M,Z,[,Z,Z,Z,Z)Y;gڭDM)X,Z,Z,Z-\+X$JrAu Bw Cx!Dx!Dx!D{!Ez!Ed8M+L+O,P-P-P-P-O,L*N,f:{!Fz!Ex!Dx!Dx!Dw Cu BsA%K+Y-\,Z,Z,Z(WLJ7cG&U,Z-\*V#HrAv Cw Cx!Dx!Dx!D{"Fx!D`6L*M+O,P-P-N+K(K(N+P-P-O,L+M+b8y!E{!Ex!Dx!Dx!Dw Cu BrA$J*W-\,Z&VH,Z^#O}"FsAv Cw Cx!Dx!Dy!D|"Fu C\4K*M+O,P-O,K(A P-p0Io.HL*B L)O,P-O,M+K*_5w C{"Fx!Dx!Dx!Dw Cv CrA#G%QRzֽLJ?\q>v Cw!Dx!Dx!Dy!D|"FrAY2J)N+O,P-O,J'>h)Bp둵둵񖻹j`";?K(O,P-O,M+J*[3u B|"Fy!Dx!Dx!Dw Cv Cp=Kfs=k 2u@x!Dx!Dx!Dy!E}"Fo>V0K*N,O,P-O,H&=t3Mz⊮އއއއ㋯sl,E=I'O,P-O,N,J*X1q@}"Fy!Dx!Dx!Dx!Dt?i 0y$Fo7k 3u@x!Dz!E}"Fk=X؂쒷ክއއއއއއއއ⊮}x6P=H&O,P-O,N,K*T/n>}"Gy!Ex!DvAm4i 0ϯ2TyBh:O,L*O,P-P-N+E $C !Gc⊭ꑵއއއ⊮玲鐴鏳印߈އއއቭ쒶܅@[@ F%N+P-P-N,K*Q-jCO,P-P-L*B P-[y퓷玲߇އއއއއ掲?^J #V.X0X/S,M &قއއއއއ߈菳ꐴTrJ(C !M*P-P-O,BC$I %O,O,K)@ Z6e印އއއއއއއއ厱Cgk6v@wBwAyCu>d䋯އއއއއއ߇捱^}S0A L)O,O,I %$i8L;>f'@o䌯އއއއއއއއއ鑴mD_u6O>Xn0I9:Z6e印߈߇އއއއ匰𕹷h^!9?<`+@մk㋮އއއއ鏳퓷كց둵ꑵ⊭ክክክ捱둵퓷쒷ց}:U>>Q.]{㋮Հ䋯퓷㋮އއއއ㋯eͮߌ߀ክއއއއއ䌯A @ A =Ϧ䒳z݆݃އ݅}}މz݄݆އއ߇鐴둵}|玲둶ክ印ڃze╴x{݄ᒱy܃݆އއއއއއއއއއއއއއއއއއއއቬ߈㊭y椿㛸w܂݆އއއއއއއއއއއއއއއއއއއއއއއއ݆~i榿w܀݆އއއއއއއއއއއއއއއއއއއއ݆܁w䟺y݆އއއއއއއއއއއއއއއއ݆܀x{~݅އއއއއއއއއއއއ݆y܁|݄އއއއއއއއ݅}}އ{݄އއއއ݄|܃x}~yފstgit-2.6.0/contrib/wix/dialog.bmp000066400000000000000000016057661520252120500170760ustar00rootroot00000000000000BM 6(8 xK\S1I #G #G #J%Z$:dsj9MH #H $M)N+O,O+N+L(G "L)_oE!I $O+P-P-P-P-P-P-P-O,N*DZ#9EM*P-P-P-P-P-P-P-P-P-P-P-O,J%P.xDN*P-P-P-P-P-P-P-P-P-P-P-P-P-O,K'N)ʹVfAO+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L)BsDWE!O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*F h6JE O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+CsS0G #O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,@yM_U3J&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F !sFXͼK'J&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E g5HBL)O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H #T1G !M*O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,J%T2q@N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,K'G #˹~SeCO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L)DwK\E O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*G "c/CE O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+@lz[#:H $O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,DUfS1I $O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,DuGZƳE K'P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E ^)>I $L)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H $\%;EM)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I $S1fv?N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-K'C\lE O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M)H $vHZCO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*B`,AF!O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+Afu_*?H #O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,O,O,O,O,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O+E]mQ.I $O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,L+N,R.T/T.P-M,M+O,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,CsFXïJ%K'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,N,Y1h:r@v Cx Cw Cv Cp?d8T0M+O,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F "c.CH $L(O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+S/l=x!Dz!Dy!Dx!Dx!Dx!Dx!Dy!Dz!Ew Cc8O,N,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G #\'<?M*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M*Y3x Dz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dx!Dx!D{"Fp?R.N+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I %K'lzDN+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+^5y Dy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!EsAU/N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,K(K(¯_oDN+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+`5z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Ev BU0M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L(H #l;NCO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+f9{"Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dy!EZ3L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*?}e2GG "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+i;z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!D_5M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+DlzY"8G "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,M+l={!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz"E`6K+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O+BZjI %J&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+Q.r@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"Fg:M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,Cj7KƳM+K'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+T/rAy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eiz!Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ea8M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O+B}ScQ/J&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,Q-p@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ef9M+O,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F!rCVϿK(K'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+P.sAz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ei;L+O,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E g5I@M)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+V1w!Dy!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Fo>P,N,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G #Q/F "N*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+Z2w Cy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ep@R.N,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,J&S2sBN*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*\4y!Dy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Es AR.M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,K&K(˺yM^BO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+b8{"Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dw DX0M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L)BsDWF!O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+e9z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dx!CZ2M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M*F !d1FEO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+i;{"Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!E]4L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+ApW 5H $O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,P,n>z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cw Cw Cw Cw Cw Cw Cw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"Ec8M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,C}SeU3I %O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,P-o?z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cv Cv Cv Cx!Dz!Ez!Ew Dv Cv Cw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ee9M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E wJ\ƳG #K'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+S/t Az!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dw Cu B}"G&O*U+X,Y+Y*W)S%Ly!Du Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"EjP-N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H $Y#8DM*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+X1w Cy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B~"F+X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[(Tw Cv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ep?P-N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I %S1ix?N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+]5{!Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtB#J,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+Wz!Eu Bw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eu BT/M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-K'DŲWgE O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+b7y!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B%L,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+X}"Gu Bw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Du CX2M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L)H $tGYDO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*e8z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cs B%M,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Z~#Gt Bw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dw!DX1L*O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*D]'M+N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,>ïAN+P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+[2z!Ey!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B"H,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[*Ux Cv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Es@R.N+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,C[k}DN+P-P-P-P-P-P-P-P-P-P-P-P-O,M+]4x!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B$I,Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Vz!Ev Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dt AT/N+O,P-P-P-P-P-P-P-P-P-P-P-P-O,E!p@S@M)P-P-P-P-P-P-P-P-P-P-O,L*a7z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtB$L,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+X|!Fu Bw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Ev CV0L+O,P-P-P-P-P-P-P-P-P-P-O,AwJ]¯K'K'O,P-P-P-P-P-P-P-O,N+g:z"Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B&O-[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#Hu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dy!D\4M+O,P-P-P-P-P-P-P-P-N+Dm{ʹN*K&O,P-P-P-P-P-O,N+i;z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu C'O,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#Iu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!D^5L+O,P-P-P-P-P-P-N*EyS1H $O,P-P-P-N,N+l>{!Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dv Cu B(R-[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[%LtBw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ea7L*O,P-P-P-P-M)Ba-BG "O,O,N,R.q@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cv Cy D)U,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[,Y)V)S(Q(R)T+X,Z,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,['Ou Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eg:N+O,P-O,L(K'b/CF!M+R.sAz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cv Cy!D*V,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[,Z'P#Gy!Dw Cv Cv Cv Cz!E$J(S,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,['PuBw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ei;N,O,K'I $ʹ}TdQ*w Cy!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B|"F+X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[(Ry!Dt Bv Cw Cw Cw Cw Cw Cw Cv CtB"H*W,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-\)Sv Cv Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"Fn>L(W 6Ժm8y Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B#H+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[&Ov Bv Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Cv Cx!D)T,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Uy Dv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Eg4ּu?vBx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct B#I,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,\&Lu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Cv Cv C(T-\,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[*Vx Cv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx Cv@=\j 1uAx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B%M,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Z$ItAw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct B'P,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+Y|"Fu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cry"E׾qm6vBx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct B'P,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+Z}"Fu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtB%L,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Z$ItAw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct?r<бRmn6w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dv Cx C)S,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[*Vx!Dv Cw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct B#I,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-[%Mu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CvAm4Lgp9w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dv Cx!D)U,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Uy!Dv Cw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B#H+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[&Nu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CvBp84Tp9w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dv By!E*V,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-\)Sv Cv Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Cu B}"F+X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-['Pu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DwBl4kz&Hrw Cv B{"F)V,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[(Rw!Cv Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dy!Dw Cu BtBtBu Bx Dz!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B}"F+X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,['Pw Cw Cw CvAp:wBq={!E*X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-\(Rv Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Er@c7Y1S/Q.Q.U/[3g:w Cz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B{!E+X,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[(Rv Bu@l 40T)X,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[&Ns Aw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eu B\4L+M+N,O,O,O,N,N,L*O-d9y!Dy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dv Cv C)U,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[(Sy#FҠ-[*Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[%Lu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ep?R.M+O,P-P-P-P-P-P-P-P-O,M+Y2v By!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cv C(R,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z)X;d޵Ś!R(W,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[%Ku Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"Fn>O,N,O,P-P-P-P-P-P-P-P-P-P-O,M+V/w Dy!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B'Q-[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Z$S>h͐K)W+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+X"Gt Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eg:M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+P-q@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtB&M,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y$S'VDŽ Q*X+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+X~"Gv Cw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ed9M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,R-o?z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B%L+Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y&U,ZnM*X,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+Wz!Eu Bw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ea7L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,N,l={"Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtA$J,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y'V!RۮSyN+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Tw Cv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dx!D[3L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+f:z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B~#G,X,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y)WM͑Pv P+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Sw Dv Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dw!CY2M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+d9z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B}"G+X,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y)XOɇ:e P+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,['Qu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ev CU0M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*_6z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dv By!D*W,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z*YKnNt!Q+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[%Nu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eq@S.N+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+[3w!Cy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dv Cx D)S,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+YM}ڮL+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z-[%Mu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eq?Q.N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+Y2x!Dy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw!Dv Cv C(S,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z*XM8c'V,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[#JtAw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"El=M+N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+S0u Bz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ct B&P,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z#SPuM+Y,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+Y#Hu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eh:N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,R.r@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B&O,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z*XO߹ɘL,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[+Y~#Gu Bw Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D|"Ee9M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,Q.q?z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cu B%M,[,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z+YK٬M,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,Z,[)Vx!Dv Bx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!E^5L*O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,M+j{!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw CtB%K,\,Z,Z,Z,Z,Z,Z,Z,Z+YOHpЙ!R)W+Y,Z,Z,Z,Z,[*Vz!Ev Cw!Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!E`5L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,N,kz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DvBm5m6Uq;w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz D`6M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+F #Fc䌰݆އއއއއއއއއއއއއއއއއ㋯ցh)BG%O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,O-k]vo8w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!En>P-N,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H&`#;|䌯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ玲`L)L*P,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+X1v Cy!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cl4Üv CvAx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!En>O,N,O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F $a$=ׁ䌯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ莳gH'K)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+U0v Cy!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dt?1Sk 2w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ff:L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,D #s2M掱⊭އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ菳zT1H&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O-N+P-qAz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Ck 3ͮm5x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Ec8M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G%;Wክቬކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆䌯z_";I'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,P-o>z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cm4ҵ˩m5x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{!Ea6M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+B !C^捱ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ䌯ցc%=E #O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,N,l=|"Fx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dm5ʧk 3w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dx!DZ2L*O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*F%Wu둶߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊭䌯y6QD #O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+e9z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cl 3׾r=vBx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Dw CY2M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L*J(\{掱އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቬቭ>YF$O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+c8y!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DwBn7_xp9x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dy!Ev CU0M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-K)H&h鐴އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ鏳GcA N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L+`5z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Ds=@^rN+N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E #e(@ك䌯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ鐳jL*K(O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+T/u Bz!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cl4Wrίt>t?w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dz!Eg9N,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F%v4N߈⊭އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ危uY5J'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,R.q@z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DwBo8mֻs=t>w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!D{"Ee9N+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,D "|9T⋭ክ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ匰zZ6H&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,Q.o?z!Ex!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DvBm5y|(Ir;w Cx!Dx!Dx!Dx!Dx!Dx!Dz!E_5L+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+D "Heꑵ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ㋯߇h)AF$O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N,M+j<{"Ex!Dx!Dx!Dx!Dx!Dx!Dx!Du@o88Wr;w Cx!Dx!Dx!Dy!Dx!C\4M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+I'Tq玱߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊭߈w5OF%O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N,g:z!Ex!Dx!Dx!Dx!Dw Cu@t@ͮ5Uo8w Cx!Dy!Dy"EY2M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*E #[y菳߇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቭ䋯|:TB !O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+e9|"Ex!Dx!Dw Ct>p9պTnn6y!Du BS/M+O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,K(O,n鑵އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ둵KgE #N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*^5y!Ex!Dr;|&Ilm:T/N+O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P,J(W2r印އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆އއއއއ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߈捱SqI&M+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,M+[3u?8XJ %M+O-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G&U1{捱އއއއއއއއއއއއއއއއއއއއއއއއއއއ݆އ匰鐳菳鐳菳鏳鐴掱ቭއ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ߇鐴]|C "L*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L*S)ǴF "M*O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F$j*Dއ㋯އއއއއއއއއއއއއއއއއއއއއއއއއއއއቭ捱`B^n-Ga#<`#;h)B~:UUru㋮䌯އ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ菳pP-J(O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,J&`-BI %L(O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G%r1Lۅ⊮އއއއއއއއއއއއއއއއއއއއއއއއއއއއ印րHe[7J(H&J(K)K)K(I'I&R/x5Op捱߈݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱rV2J(O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H #^(=BM)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,C !~;V匰ቭއއއއއއއއއއއއއއއއއއއއއއއއއއއއꐴdU1E #M*O,O,P-P-P-P-O,O,N+H&G%E`捱ቭއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱|[7G%O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I $P-lzCN+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+G%Kh玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއ掲MiF #L*P,P-P-P-P-P-P-P-P-P-P-P-N+F$h)Bڄቭއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ㋮څm.FG%O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,K'I $aqDN+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M+E $Rp捱߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއ菲YxE #N+P,P-P-P-P-P-P-P-P-P-P-P-P-P-O,G$o/I匰߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊮݇s1KF$O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L(H %sEVCO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L*F%`둵އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊭xD "N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,C !Jg菳އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቬ菳>ZC !N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M*Ad1EG "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P,K(R.k莳އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ鐳g)BJ'P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,P,N+H&}ቬއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆玱LiG%N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+Djxa,AG "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P,I'Q.p掲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቭy> L+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+M+C #Ie玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆߈玲RoE #M*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O+Ccrg5HF !O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,G%_":~捱އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ危Mn`3g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:g:e8p#B掱އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ둵cJ(L)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,@iwBO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H%j+Dׁ㋮އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ琳6YuAy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dy!Dx Dr=݆߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱kR.K)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+B^(>K'P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,C "m-F߇㋮݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ葴*MuAx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cn:}އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ玲sN,I'P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-H $sFW@O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+E #?Z둵݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ葴*MuAx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cn:}އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݇挰ك`#;G%O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O+AŲAO,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+F%Gd䌰߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ琳7Zt@x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cr>݆߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݇㋮ׁj+CG&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,@ͻBP-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M+C !Qo菳߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ䍰Qsq=x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!DuA,O揲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊮q1KC "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-B˹@O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L*K)c鑴އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ|m9w Cx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dt@;^揲߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ玲C^E $N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-AðCO+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-K)N*f珲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ揲4Ws?x!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dx!Dw Cs?Il㌯߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݇印HdE$N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,@g6IJ&P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I'P,s菳އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ{pb匰ክއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݇߈ꐴTqC !M+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L(V5ϾAO+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H&_":|匰އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ厱_R+Z1\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3\3U-o,Gׁ㋯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ菳aL)L)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,BZkCO,P-P-P-P-P-P-P-P-P-P-P-P-P-O,G%c%?䌯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ危QmD#J(M,M,M,M,M,M,M,M,M,M,M,M,M,M,M,M,M,M,M,M+G%e&?Հ䌯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ玲gL)K)O,P-P-P-P-P-P-P-P-P-P-P-P-P-O,H #a,AyM_BO,P-P-P-P-P-P-P-P-P-P-P-O,D #s2L⊭⊮އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއꐴgX4D "K)O,O,P-P-P-P-O,O,N+O,P-P-P-P-P-P-P-P-O,H&U0v玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ菳uU2I&O,P-P-P-P-P-P-P-P-P-P-P-O,H #U3_oEO+P-P-P-P-P-P-P-P-P-O,G%?Z⊮ቬއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ勰؂Nk_":K*H&I'K(K(J(H&J(W3K)O,P-P-P-P-P-P-P-P-O,K(Q-j掱އ݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ䌯|c$=H&O,P-P-P-P-P-P-P-P-P-O,G #`,Ak{@N+P-P-P-P-P-P-P-N,A D`捱އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቬ掱؂eJfv4Oj*Dg(Ap0IA\\z}~;VC "O,P-P-P-P-P-P-P-P-P-K)L)gꐵއ݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ䌯؂c%=E$O,P-P-P-P-P-P-P-O,Ec0DDM)P-P-P-P-P-M+E #Us쒶߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆އ䌯鏳鏳菲莲菳鐴危⊭ꑵJfC "N+P-P-P-P-P-P-P-P-P-M*B !Wuꏳ߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊭捱u4MD #O,P-P-P-P-P-O+C|PaJ'L)P-P-P-M*K)]{玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆އއއއ݆݆އ߈玲RpG%M+P-P-P-P-P-P-P-P-P-N+H&Nj捱߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆ቬ⊮>YG%O,P-P-P-O+E!fuIJDK'P-K)H'f菳އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߇鏴[yD "L*P-P-P-P-P-P-P-P-P-N+E #Fb鑵݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆掱DaA N+P-N+>p~T1D V3w玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއꐴnP-K(O,P-P-P-P-P-P-P-P-O,C "t2M⊭݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߈둵XwG%K'Ef,Cu䌰އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ印pU2J(P,P-P-P-P-P-P-P-P-O,G%o/H܅⊮݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱\|J'㑲≭އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆އއއ݆݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱{Y4G&O,P-P-P-P-P-P-P-P-O,F$a$<ڃ匱އ݆݆އއއ݆݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ勯Ј܃ބ݆އއއއއއއއއއއއއއއއއއއއއއއއއއ݇އ߇ቭ㋯匰匰䌰䋯⊭߇އކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ㋯܆j*DF$O,P-P-P-P-P-P-P-P-O,I'T1u捱㋮䌯匰䌰䋯㊮߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߄◵݄݄݆އއއއއއއއއއއއއއއއއއއއއއއއއއ݇匰ቭzhZyUsZxhy匰އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊮܅q0JE$O,P-P-P-P-P-P-P-P-O,J(U1pۄo_~WtYwbs܅䌰⊭އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܁▴~݄އއއއއއއއއއއއއއއއއއއއއއއއއއއ߇菲كSqh)BM+E#F$F$F#E #M*g'@Pmׂ玲߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއቭ捰=XC !N,P-P-P-P-P-P-P-P-P-K)P,X4F%E $E $E #E #H&[7B]t鏴ቬއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ܁މ݅އއއއއއއއއއއއއއއއއއއއއއއއއއއ㋮WuU1G%K)N+O,O,P-O-O,N+K)G%S1Tp㋮އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捰JgG%N+P-P-P-P-P-P-P-P-P-N+M*O,O,P-P-O,O,L*H&K)=XՀ䋯އއއއއއއއއއއއއއއއއއއއއއއއއއއއކ܃݅~݅އއއއއއއއއއއއއއއއއއއއއއއއއއއ䋯>ZG%L)O,O,P-P-P-P-P-P-P-O-O,L)E #|9T㌮އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߈玱PmD #M+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,N+F%_"9y匰އއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݄܃壾|݆އއއއއއއއއއއއއއއއއއއއއއއއއއއ߈玲p/JC !O,P-P-P-P-P-P-P-P-P-P-P-P-P-O,C "j+E䌰߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߇둵aH&L*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,I(M*w㋯އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅|䜺܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ菳FbE #O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E $@[둵䋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯㋯䋯퓷oV3M+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-J(Z7߇߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއክyC !O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,H&Ut\{[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[z[zbC^K(O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,D #Jg鏳އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅}z݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއꑵo/HI'P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,E #D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "D "H'P,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-N+D #݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅|▵܃އއއއއއއއއއއއއއއއއއއއއއއއއއއއއۄH&N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,D "\z匰އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ܁榿~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ㋮iC !O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-I'{8S鐴އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅܁|ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ印TrF$P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L)a#;쒶އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆{}އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱PlF$P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L*\7쒶އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ}|އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ匰XvE #P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-K)f(B쑵݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ}}݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊮qC "O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-H&D_菳݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆}݃އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߈ክM*N+P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,L)I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I&I'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-E #g玲݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݈݅{݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއ鐴C_F$P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-I'r1KUrQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnQnSoKhF$O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-L)`#<捰އއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ~墾ۀ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއۄN+M*P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-M+L)Հ玲䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯䌯匰둵s1KH&O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,J'V3oކއއއއއއއއއއއއއއއއއއއއއއއއއއކ܃ߎ܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ玱^~A N,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,A Xv玲އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ⊭~M+K)P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,D \%;褿݆އއއއއއއއއއއއއއއއއއއއއއއއކ݃܀㝹~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއ둶QmB !M*O,P-P-P-P-P-P-P-P-P-P-P-O,M*B !Li됶އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ印sM+I'O,P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-P-O,F !`+?}݆އއއއއއއއއއއއއއއއއއއއއއ݆܂݆݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއ捱ZxQ.I'O,P-P-P-P-P-P-P-P-P-O,I'N,Us玱އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ匰ra"P{݅އއއއއއއއއއއއއއއއއއ݆݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއ㊮ꐵyKgj+EX4P,L*O,X4j*CHfw鐴⊮އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއꐴڃVtt3M^!8Q.L*M+U1c&>@[WvJ(L*N+Ces܂݄ކއއއއއއއއއއއއއއއ݆墽܁݅އއއއއއއއއއއއއއއއއއއއއއއއއއއ݇އክ䌰܆|ust|܆䌯⊭އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆㋯Հwqszڃ⋮鏳fL)D tޅ݃ކއއއއއއއއއއއއއ݆}݄އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ߈⊭⊮⊭߈އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆އ߇⊭⊮⊮ክ߈އއ菳c݅܂ކއއއއއއއއއއއ݆{އ܂݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆݆݆އއއއᇫ鞼܁݆އއއއއއއއއ݅~ߋ܂݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ܁ᒱ▴܀݆އއއއއއއ݄܀ᑱ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ܂݇䞺}݆އއއއއ݃܁垺܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݃܂݆އއ݆܂މ墽~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݄܁~݆݅܂ފ|݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅|}~ᔳ܀݅ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆㛹}݅ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆~݃݃ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆}㚸ވ܃ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܁ᕴ݆܁ކއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܁ᔳ܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܂܃䜹܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݆݃椿}݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݆݇އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆ۀ▵~݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆㛸}݄އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆|݄݄݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܃݆݃އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅}ߌ܁݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݄ᕴ܁݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆݄݅▴~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܃܁}݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܁ߌ݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܁ᓳ{݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆~◵܀݄އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆~܃݄އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܂܃އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅{ߍ܁݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݄܀܁݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݄܂㛸~݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ܂݆݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܂ߏ}݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܀}݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆~䞺܁݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆}݄އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆{݇܂݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݅ߌ܂݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݄܂܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݄䝹݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܂އ椾݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆܂ߋ}݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆ᒲ܀݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆堼~݅އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆~棾܀݃އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއއ݆|ވ܃݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݅ކ܂݆އއއއއއއއއއއއއއއއއއއއއއއއއއއއކ݅|ᔳ܀݆އއއއއއއއއއއއއއއއއއއއއއއއއއކ݃܂㜹܀݆އއއއއއއއއއއއއއއއއއއއއއއއކ܃މ堻|݆އއއއއއއއއއއއއއއއއއއއއއކ܁݇}݆އއއއއއއއއއއއއއއއއއއއ݆܀ᔴ݅އއއއއއއއއއއއއއއއއއ݆܀㜹}݅އއއއއއއއއއއއއއއއ݆}椾܃݄݆އއއއއއއއއއއއއ݆݅݅݃އއއއއއއއއއއ݅ߌ݅ކއއއއއއއ݆܂݄܁݄݆݆݆݆݅܂܁☵ߍ܂܁܁܁߉䞺stgit-2.6.0/contrib/wix/gpl-2.0.rtf000066400000000000000000000443711520252120500167170ustar00rootroot00000000000000{\rtf1\ansi\ansicpg1252\deff0\nouicompat{\fonttbl{\f0\fnil\fcharset0 Courier New;}} {\colortbl ;\red0\green0\blue255;\red0\green0\blue128;} {\*\generator Riched20 10.0.22621}\viewkind4\uc1 \pard\nowidctlpar\sa180\kerning1\ul\b\f0\fs16\lang1033 GNU GENERAL PUBLIC LICENSE\ulnone\par Version 2, June 1991\par Copyright (C) 1989, 1991 Free Software Foundation, Inc. \line 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA\line\line Everyone is permitted to copy and distribute verbatim copies\line of this license document, but changing it is not allowed.\par \ul Preamble\ulnone\par 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.\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 \ul TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\ulnone\par \par 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".\par 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 \par 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.\par 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 \par 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:\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 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.\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 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.)\par \pard\nowidctlpar\sa180 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 \par 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:\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 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,\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 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,\par \pard\nowidctlpar\par \pard\nowidctlpar\li360 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.)\par \pard\nowidctlpar\sa180 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 \par 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.\par \par 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.\par \par 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.\par \par 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.\par 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 \par 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.\par \par 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.\par 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 \par 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.\par \par NO WARRANTY\par 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.\par \par 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.\par END OF TERMS AND CONDITIONS\par \ul How to Apply These Terms to Your New Programs\ulnone\par 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.\par 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.\par one line to give the program's name and an idea of what it does.\line Copyright (C) yyyy name of author\line\line 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.\line\line 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.\line\line 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.\par Also add information on how to contact you by electronic and paper mail.\par If the program is interactive, make it output a short notice like this when it starts in an interactive mode:\par Gnomovision version 69, Copyright (C) year name of author\line Gnomovision comes with ABSOLUTELY NO WARRANTY; for details\line type `show w'. This is free software, and you are welcome\line to redistribute it under certain conditions; type `show c' \line for details.\par 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.\par 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:\par Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker.\line\line signature of Ty Coon, 1 April 1989\line Ty Coon, President of Vice\par 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 {{\field{\*\fldinst{HYPERLINK "https://www.gnu.org/licenses/lgpl.html" }}{\fldrslt{\ul\cf1\cf2\ul\lang255 GNU Lesser General Public License}}}}\f0\fs16 instead of this License.\par } stgit-2.6.0/contrib/wix/stgit.wxs000066400000000000000000000154661520252120500170230ustar00rootroot00000000000000 stgit-2.6.0/examples/000077500000000000000000000000001520252120500144615ustar00rootroot00000000000000stgit-2.6.0/examples/gitconfig000066400000000000000000000064301520252120500163600ustar00rootroot00000000000000# StGit configuration file. Copy it to any of ~/.gitconfig or # .git/config and modify as needed. Note that the latter overrides # the former. The "git config" command can be used as well [user] # Default author/committer details (standard Git variables) name = Your Name email = your.name@yourcompany.com [stgit] # E-mail sender (added to the "From: " header) #sender = Your Name # Automatically Bcc the address below #autobcc = your.name@yourcompany.com # Automatically sign newly created patches #autosign = Signed-off-by # SMTP server for sending patches #smtpserver = /usr/sbin/sendmail -t -i #smtpserver = localhost:25 # Set to 'yes' to use SMTP over TLS #smtptls = no # Username for SMTP authentication, required if TLS is used #smtpuser = username # Password for SMTP. If not provided, it will be asked #smtppassword = password # delay between messages in seconds (defaults to 5) #smtpdelay = 5 # stg will look for this first, then look for the EDITOR environmental # variable, then default to using 'vi' #editor = /usr/bin/vi # this value overrides the default PAGER environment variable #pager = less -FRSX #pager = filterdiff --annotate | colordiff | less -FRSX # Git pull and fetch commands (should take the same arguments as # git fetch or git pull). By default: #pullcmd = git pull #fetchcmd = git fetch # Rebase command. Note that this command is internally implemented in # a different way. Only define this option if a different rebase # is needed (i.e. 'git svn rebase') #rebasecmd = git reset # "stg pull" policy. This is the repository default, which can be # overridden on a per-branch basis using branch.*.stgit.pull-policy # By default: #pull-policy = pull # To support remote rewinding parent branches: #pull-policy = fetch-rebase # To support local parent branches: #pull-policy = rebase # Automatically invoke the interactive merger (git mergetool) in case # of conflicts #autoimerge = no # Optimize (repack) the object store after every pull #keepoptimized = yes # Extensions for the files involved in a three-way merge (ancestor, # current, patched) #extensions = .ancestor .current .patched # The number of patches to be listed before and after the # current one by the 'series --short' command #shortnr = 5 # The maximum length of an automatically generated patch name #namelength = 30 # Extra options to pass to "git diff" (extend/override with # -O/--diff-opt). For example, -M turns on rename detection. #diff-opts = -M # Behave as if the --keep option is always passed #autokeep = no # Behave as if the --autostash option is always passed to rebase #autostash = no # Include submodules by default when refreshing patch contents. #refreshsubmodules = no [stgit "pick"] # The the format applied to the commit message when using # "stg pick --expose". See the "PRETTY FORMATS" section of # git-show(1) for format syntax details. #expose-format = format:%B%n(imported from commit %H) [stgit "alias"] # Command aliases. #add = git add [mail "alias"] # E-mail aliases used with the 'mail' command git = git@vger.kernel.org [stgit "color"] # Specify output colors for series commands applied = green_foreground current = red_foreground unapplied = white_foreground hidden = cyan_foreground stgit-2.6.0/examples/patchdescr.tmpl000066400000000000000000000000671520252120500175020ustar00rootroot00000000000000 Signed-off-by: Your Name stgit-2.6.0/src/000077500000000000000000000000001520252120500134325ustar00rootroot00000000000000stgit-2.6.0/src/alias.rs000066400000000000000000000167111520252120500150770ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0-only //! Support for built-in and user-defined command aliases. use std::collections::BTreeMap; use anyhow::{anyhow, Result}; use bstr::ByteSlice; /// Mapping of alias names to [`Alias`] structs. pub(crate) type Aliases = BTreeMap; /// Kind of command alias: `Shell` or `StGit`. #[derive(Debug, Clone, Copy)] pub(crate) enum AliasKind { /// Shell aliases are executed with the system shell (typically `bash`). Shell, /// StGit aliases name/invoke builtin StGit subcommands. StGit, } /// Command alias #[derive(Debug)] pub(crate) struct Alias { pub kind: AliasKind, pub name: String, pub command: String, } impl Alias { /// Create new command alias. /// /// If the command string begins with `!`, it will be treated as a shell alias, /// otherwise it will be an alias for a StGit command. pub(crate) fn new(name: &str, command: &str) -> Self { let (kind, command) = if let Some(command) = command.strip_prefix('!') { (AliasKind::Shell, command.to_string()) } else { (AliasKind::StGit, command.to_string()) }; Self { kind, name: name.into(), command, } } /// Make [`clap::Command`] for the alias. pub(crate) fn make(&self) -> clap::Command { let about = match self.kind { AliasKind::StGit => format!("Alias for `stg {}`", &self.command), AliasKind::Shell => format!("Alias for shell command `{}`", &self.command), }; clap::Command::new(self.name.clone()) .about(about) .trailing_var_arg(true) .arg( clap::Arg::new("args") .help("Extra arguments to aliased command") .num_args(1..) .allow_hyphen_values(true), ) } /// Split the alias' command line into words vector. pub(crate) fn split(&self) -> Result, String> { split_command_line(&self.command) } } /// Generate mapping of built-in aliases. pub(crate) fn get_default_aliases() -> Aliases { let aliases: Aliases = BTreeMap::from( [ ("add", "!git -C \"$GIT_PREFIX\" add"), ("mv", "!git -C \"$GIT_PREFIX\" mv"), ("resolved", "!git -C \"$GIT_PREFIX\" add"), ("rm", "!git -C \"$GIT_PREFIX\" rm"), ("status", "!git status -s"), ] .map(|(name, command)| (name.into(), Alias::new(name, command))), ); aliases } /// Get user-defined aliases from the git configuration. /// /// The `exclude` closure is intended to prevent names of builtin StGit subcommands from /// being shadowed by aliases. pub(crate) fn get_aliases(config_file: Option<&gix::config::File>, exclude: F) -> Result where F: Fn(&str) -> bool, { let mut aliases = get_default_aliases(); if let Some(config_file) = config_file { if let Some(sections) = config_file.sections_by_name("stgit") { for section in sections .filter(|section| section.header().subsection_name() == Some("alias".into())) { for value_name in section.value_names() { let name = value_name.to_str().map_err(|_| { anyhow!( "alias name `{}` in {} is not valid UTF-8", value_name.to_str_lossy(), config_source_str(section.meta().source), ) })?; if let Some(value) = section .value(value_name) .and_then(|v| (!v.is_empty()).then_some(v)) { if !exclude(name) { let command = value.to_str().map_err(|_| { anyhow!( "alias value for `{name}` in {} is not valid UTF-8", config_source_str(section.meta().source) ) })?; let alias = Alias::new(name, command); aliases.insert(name.to_string(), alias); } } else { aliases.remove(name); } } } } } Ok(aliases) } /// Split command line string into words. /// /// Single- and double-quoted substrings are preserved. fn split_command_line(line: &str) -> Result, String> { let mut argv = Vec::new(); let mut quote: char = '\0'; let mut skip_spaces = true; let mut post_backspace = false; let mut word = String::new(); for c in line.chars() { if post_backspace { word.push(c); post_backspace = false; } else if c.is_ascii_whitespace() { if !skip_spaces { if quote == '\0' { let completed_word = std::mem::take(&mut word); argv.push(completed_word); skip_spaces = true; } else { word.push(c); } } } else { skip_spaces = false; if quote == '\0' && (c == '\'' || c == '"') { quote = c; } else if c == quote { quote = '\0'; } else if c == '\\' && quote != '\'' { post_backspace = true; } else { word.push(c); } } } if post_backspace { Err("command line ends with \\".to_string()) } else if quote != '\0' { Err("unclosed quote".to_string()) } else { argv.push(word); Ok(argv) } } /// Map [`gix::config::Source`] to user-facing strings. fn config_source_str(source: gix::config::Source) -> &'static str { use gix::config::Source; match source { Source::GitInstallation => "git installed config", Source::System => "system config", Source::Git => "git config", Source::User => "user global config", Source::Local => "repository local config", Source::Worktree => "worktree config", Source::Env => "environment config", Source::Cli => "cli config", Source::Api => "api config", Source::EnvOverride => "environment override config", } } #[cfg(test)] mod tests { use super::*; #[test] fn split_command_lines() { assert_eq!( split_command_line("git status"), Ok(vec![String::from("git"), String::from("status")]) ); assert_eq!( split_command_line("cat \"foo bar\""), Ok(vec![String::from("cat"), String::from("foo bar")]) ); assert_eq!( split_command_line("cat \"foo 'bar'\""), Ok(vec![String::from("cat"), String::from("foo 'bar'")]) ); assert_eq!( split_command_line("cat \"foo \\\" 'bar'\""), Ok(vec![String::from("cat"), String::from("foo \" 'bar'")]) ); assert_eq!( split_command_line("cat 'dog"), Err("unclosed quote".to_string()), ); assert_eq!( split_command_line("cat \"dog'"), Err("unclosed quote".to_string()), ); assert_eq!( split_command_line("cat dog\\"), Err("command line ends with \\".to_string()), ); } } stgit-2.6.0/src/argset.rs000066400000000000000000000136251520252120500152740ustar00rootroot00000000000000// SPDX-License-Identifier: GPL-2.0-only //! [`clap::Arg`] definitions common to several StGit commands. use bstr::ByteSlice; use clap::Arg; use crate::branchloc::BranchLocator; /// The `--branch`/`-b` option for selecting an alternative branch. pub(crate) fn branch_arg() -> Arg { Arg::new("branch") .long("branch") .short('b') .help("Use instead of current branch") .num_args(1) .value_name("branch") .value_hint(clap::ValueHint::Other) .value_parser(clap::value_parser!(BranchLocator)) } /// The `--keep/-k` option. pub(crate) fn keep_arg() -> Arg { Arg::new("keep") .long("keep") .short('k') .help("Keep the local changes") .action(clap::ArgAction::SetTrue) } /// The `--merged` option checking for already-merged patches before pushes. pub(crate) fn merged_arg() -> Arg { Arg::new("merged") .long("merged") .short('m') .help("Check for patches merged upstream") .action(clap::ArgAction::SetTrue) } /// The --conflicts option determining how push-time conflicts are handled. pub(crate) fn push_conflicts_arg() -> clap::Arg { clap::Arg::new("conflicts") .long("conflicts") .help("\"allow\" or \"disallow\" pushing a patch with conflicts") .long_help( "Either \"allow\" or \"disallow\" pushing a patch with conflicts.\n\ \n\ Using `--conflicts=allow` (or just `--conflicts`) allows pushing a patch \ that may result in unresolved merge conflicts. The patch will be pushed \ and files with conflicts will be left with conflict markers to be \ resolved manually; or the operation undone with `stg undo --hard`. This \ is the default behavior and also corresponds to the \ \"stgit.push.allow-conflicts\" variable being set to \"true\".\n\ \n\ Using `--conflicts=disallow` disallows pushing any patch that would \ result in merge conflicts. The operation will stop on the last patch that \ can be pushed without conflicts. This behavior can be configured by \ setting \"stgit.push.allow-conflicts\" to \"false\".", ) .hide_possible_values(true) .value_name("policy") .value_parser(["allow", "disallow"]) .num_args(0..=1) .require_equals(true) .default_missing_value("allow") .action(clap::ArgAction::Set) } pub(crate) fn committer_date_is_author_date_arg() -> clap::Arg { Arg::new("committer-date-is-author-date") .long("committer-date-is-author-date") .alias("cdiad") .help("Use author date as committer date") .long_help( "Instead of using the current time as the committer date, use the author \ date of the commit as the committer date.", ) .action(clap::ArgAction::SetTrue) } /// The `--diff-opt`/`-O` option for pass-through to subordinate `git` processes. pub(crate) fn diff_opts_arg() -> Arg { Arg::new("git-diff-opt") .long("diff-opt") .alias("diff-opts") .short('O') .help("Pass additional