Compare commits

...

98 commits

Author SHA1 Message Date
Adrian Miranda 63c0e77aaf
fix: handle browser paths safely (#234)
Some checks failed
CI / basics (push) Has been cancelled
2026-05-24 21:06:15 -04:00
Prabhu Jayakumar 41ebfcebe1
Add support for bitbucket repos cloned with ssh (#174) 2026-02-24 08:09:33 -08:00
Sam Saccone f4832493a0
tests: add test for open.default.remote configuration (#226)
Co-authored-by: Sam Bo <agent@openclaw.ai>
2026-02-14 07:21:58 -08:00
Simon Olofsson 477b196a1d
README: Add Bash section for Oh-My-Bash (#214) 2026-01-14 12:57:31 -08:00
sixther a223125abc
Added support for cnb.cool. (#217)
Co-authored-by: ericdduan <ericdduan@tencent.com>
2025-03-19 12:07:49 -07:00
Rob Loach 2a66fcd7e3
Add oh-my-bash support (#213)
Some checks failed
CI / basics (push) Has been cancelled
2024-10-03 18:17:24 -07:00
Paul Irish ce881820db make shellcheck happy. #170
Some checks failed
CI / basics (push) Has been cancelled
2024-08-05 17:08:25 -07:00
Paul Irish a7d09090c2 add a test for new --file option. ref #170 2024-08-05 17:06:40 -07:00
Paul Irish 866c39dbf4 add npmignore to avoid publishing bats-assert/support 2024-08-05 16:57:16 -07:00
Paul Irish 64cf066704 3.1.0 2024-08-05 16:54:16 -07:00
Paul Irish a437297494 package: repo fix 2024-08-05 16:54:03 -07:00
Brian Wellington dd22397400
Add --file option. (#170) 2024-08-05 16:52:18 -07:00
Sandro 5d1f938b47
Use absolute PATH to powershell.exe (#204)
Some checks failed
CI / basics (push) Has been cancelled
2024-07-05 07:03:11 -07:00
Majid Alaeinia d086ab0077
readme: zsh: Consider sourcing ~/.zshrc (#209) 2024-02-21 11:26:09 -08:00
Sandro 281dad270e
Add gitea support (#184) 2023-05-02 11:29:10 -07:00
Paul Irish f772364eb8 adjust http preservation test 2022-07-18 15:29:03 -07:00
Paul Irish 17491478e6 3.0.0 2022-07-18 15:17:02 -07:00
Paul Irish 0b626514bb
move to github actions (#192) 2022-07-18 14:19:56 -07:00
Paul Irish 1a93477f70 update dependencies 2022-07-18 13:30:29 -07:00
Sowmiya M f11ced9a4f
Remove unused code and fix double-negation (#153) 2022-07-18 13:30:13 -07:00
Paul Irish 0b6b0a2b40 package-lock.json update 2022-07-18 13:10:50 -07:00
ratijas ca0214c0d6
Fix broken links in changelog (#172) 2022-07-18 12:46:58 -07:00
kazufusa 8ac94bf7c3
gitlab: fix issue ID parsing (#183) 2022-07-18 12:46:28 -07:00
John Meyer 0296983a28
WSL: do not load PowerShell profile (#190) 2022-07-18 12:37:31 -07:00
Dave Wikoff 14fdf5c96e Merge branch 'pull-165' into master 2020-08-21 15:09:30 -07:00
Dave Wikoff ca8b2348f2 Fix bitbucket tests 2020-08-21 15:02:54 -07:00
Heechul Ryu c908a50824 Delete the comment for issue #80 2020-07-08 11:10:29 +01:00
Heechul Ryu 0189caeb4b Open bitbucket with the right branch
replace from `?at` to `/` for `providerBranchRef`
2020-07-08 11:10:29 +01:00
Dave Wikoff 3e8c908dcd
Merge pull request #166 from glostis/fix-suffix
Fix suffix with `=` in it
2020-07-07 14:46:30 -07:00
Guillaume Lostis 3bd3524de2 Fix shellcheck 2020-06-19 14:02:31 +02:00
Guillaume Lostis 1d55c4ee50 Fix formatting to pass shellcheck 2020-06-19 12:35:48 +02:00
Guillaume Lostis 91170cd5c8 Fix handling of suffix with = in it 2020-06-19 12:11:53 +02:00
Guillaume Lostis 9a35780c09 Add test for suffix with = in it 2020-06-19 12:11:29 +02:00
Dave Wikoff d9a0d19ce2
Merge pull request #149 from rec/documentation
Document flags to git-open
2019-12-22 13:55:37 -05:00
Dave Wikoff 849298fece
Detect WSL case insensitively (#158)
Detect WSL case insensitively
2019-12-22 13:32:17 -05:00
Víctor ad8fac9309
Detect WSL case insensitively
My `uname -r` is `4.19.81-microsoft-standard`
2019-11-26 10:54:37 +01:00
Frank Fesevur fcbbf918f7
Merge pull request #154 from dineshba/master
Add suffix flag
2019-09-16 07:56:38 +02:00
Dinesh 8b909f81dc Add suffix flag
Co-authored-by: Sowmiya <sowmiyamuthuraman@gmail.com>
2019-09-07 23:08:13 +05:30
Tom Ritchford d52366d8c9 Document flags to git-open 2019-07-29 15:18:33 +02:00
Dave Wikoff 08fa2abd7e
Add a --commit option (#144)
Add a --commit option
2019-07-09 12:21:32 -04:00
Domenico Gemoli 0564817aef Adding a --commit option.
I've only tested this with gitlab seeing as I needed it there. If this could be useful I can integrate any feedback you might have to get this proposal merged.
2019-07-08 23:34:13 +02:00
Dave Wikoff 44382bf541
Merge pull request #143 from arunvelsriram/print-option
Add option to print the url
2019-07-06 13:17:10 -04:00
Arunvel Sriram 8239d0a785 Add option to print the url 2019-07-03 21:32:34 +05:30
Dave Wikoff 7eeee771ce
default to upstream branch (#140)
default to upstream branch
2019-06-02 13:35:38 -04:00
Love F 3d1ad212b2 default to upstream branch 2019-06-02 14:24:41 +02:00
Paul Irish 4eed00f282
Fix shellcheck on travis (#134) 2018-12-03 18:24:29 -08:00
Paul Irish 556dbe91f2
readme: add 2.1.0 release to mini changelog 2018-12-03 11:09:06 -08:00
Paul Irish 5344a73106 -> v2.1.0 2018-12-03 10:59:46 -08:00
Paul Irish 5eba420570 npm audit fix 2018-12-03 10:55:18 -08:00
Paul Irish f02d7e97b0 add package-lock.json 2018-12-03 10:55:18 -08:00
Dave Wikoff 301c5a619e
Merge pull request #132 from neersighted/patch-1
Remove openopt, allow spaces in $BROWSER
2018-11-22 20:11:25 -05:00
Bjorn Neergaard 96c80ffe80 Remove openopt, allow spaces in $BROWSER
Remove the openopt variable, instead opting to allow spaces in `$BROWSER`.

`$BROWSER` as used by the XDG implementation allows spaces (and `%s`
printf-style formatting strings), and is actually a PATH-style list.
While this patch doesn't make git-open compliant with the XDG-style
variable, it does allow for the use of `BROWSER="powershell.exe
Start"` in the environment.
2018-11-21 14:01:33 -07:00
Dave Wikoff 4ca19904a2
Merge pull request #130 from orestisf1993/tags-commits
Support opening current tag / commit
2018-09-17 11:08:39 -04:00
Orestis Floros 8c8c41bd50
Support opening current tag / commit
Fixes #89.
Fixes #129.
2018-09-14 05:28:58 +03:00
Dave Wikoff 5fefffede3
Merge pull request #128 from crossroad0201/master
Supports AWS Code Commit.
2018-08-16 17:49:40 -04:00
Y.Tsuji 6bb49c28c5 Fix Indentation. 2018-08-13 01:55:43 +09:00
Yohei TSUJI c5e636f423 Append 'AWS Code Commit' to supported remote repositories. 2018-08-10 15:56:39 +09:00
Yohei TSUJI 2ef17f07d8 Added test cases for AWS Code Commit. 2018-08-10 15:56:21 +09:00
Yohei TSUJI c68b9c16e8
Merge pull request #1 from crossroad0201/supports_aws_code_commit
Added support for AWS Code commit.
2018-08-08 14:20:13 +09:00
Yohei TSUJI 557fd40b1c Added support for AWS Code commit. 2018-08-08 13:58:57 +09:00
Dave Wikoff 995e91591f Swap uppercase/lowercase for ssh feature (#123) 2018-04-29 17:31:30 -07:00
Dave Wikoff d24f64da48
Merge pull request #122 from derimagia/uppercase-bash-3
Fix issue #121 - incompatability with bash < 4
2018-04-27 10:23:50 -04:00
Dave Wikoff 895240ff03 Fix issue #121 - incompatability with bash < 4 2018-04-27 10:19:56 -04:00
Paul Irish 4b1e8601a7
Merge pull request #120 from 4U6U57/119-fix-markdownlint
Fixes markdownlint for build
2018-02-26 23:44:28 -08:00
August Valera c3fd9a48df Revert gitignore package-lock, fix #115
Remove package-lock.json from gitignore for npm
Fix bug in #115 that modified user's gitconfig when running tests
2018-02-26 22:15:35 -08:00
August Valera 5b815cb619 Fix current errors in Markdown files
Also: add package-lock.json to gitignore
Remove prefix $ for commands in the manpage, hope people aren't angry
Add MD034 to markdownlint ignore (bare links, which are helpful for the
manpage)
2018-02-24 22:00:30 -08:00
August Valera 702b8a6fc6 Change dependency markdownlint to markdownlint-cli
markdownlint-cli is the recommended cli for the markdownlint package
See https://www.npmjs.com/package/markdownlint#related

Unit tests should now fail due to markdownlint actually linting md files
2018-02-24 21:50:18 -08:00
Dave Wikoff d049d441b3
Merge pull request #114 from Jaxwood/master
Fix bug with open -i on default VSTS project repo
2018-02-21 20:37:32 -05:00
Jacob Lorenzen aea6e3edb7
Add comment on default VSTS repository urls 2018-02-20 18:20:01 +01:00
Dave Wikoff d9b958087d
Merge pull request #109 from 4U6U57/master
Support domain expansion from sshconfig
2018-02-19 15:06:32 -05:00
August Valera 775361b509 Fix shellcheck 2018-02-15 22:23:37 -08:00
August Valera 8909a2b753 Adds support for sshconfig expansion
See `man ssh_config` for documentation for sshconfig.
Only works on SCP-like remote URL's [user@]hostalias:path/to/repo.git
Parses through ~/.ssh/config, looking for a Host entry matching
hostalias (bash-like pattern matching supported) and expanding it to the
corresponding HostName entry, if applicable.
2018-02-04 12:12:48 -08:00
Dave Wikoff 7449bfa7e1
Merge pull request #115 from larsks/feature/ls-url
Use ls-remote --get-url to get remote url
2018-02-04 12:06:54 -05:00
Dave Wikoff beebcdbf37
Merge pull request #113 from nwinkler/bb-server-context
Bitbucket Server Root Context
2018-02-04 11:32:28 -05:00
Lars Kellogg-Stedman 740222babf Use ls-remote --get-url to get remote url
As noted in a comment, 'git ls-remote --get-url' will expand insteadOf
mappings.  I use a number of shortcuts (like gh: for git on github,
lp: for git on launchpad, me: for my github repositories, etc), so I
was constantly hitting situations in which git-open would fail to do
the right thing.

It looks like '--get-url' has been available since git 2.12.0.
2018-02-02 10:41:54 -05:00
Jacob Lorenzen 67b72ac0f2 Fix bug with open -i on default VSTS project repo
The default VSTS clone url is different from other project repository urls

e.g. Default repository url: https://gitopen.visualstudio.com/_git/Project
     Sibling repository url: https://gitopen.visualstudio.com/Project/_git/Repository

     Trying to use git open -i on the default repository will lead to an
     url formatted as https://gitopen.visualstudio.com/_git/Project/_workitems?id=xx
     This url is malformed as the _git part should not be part of it.

     This change will fix this bug and correctly format url as
     https://gitopen.visualstudio.com/Project/_workitems?id=xx.
2018-01-24 13:41:02 +01:00
Dave Wikoff 51caa23c63
Merge pull request #110 from ffes/add-man-page
Add man page
2018-01-22 11:08:08 -05:00
Nils Winkler 140edbbcee Fixed test names to match existing tests
Also removed some duplicated tests that were introduced during a
previous merge.
2018-01-11 08:18:42 +01:00
Nils Winkler 119ada7f69 Removed an unnecessary if statement 2018-01-10 07:53:44 +01:00
Nils Winkler 24dd2fc5fc Added support for Bitbucket Server with different root context
Please see the unit tests for more details. Basically, take the context
parts before 'scm' and add them to the new URL before the other parts.

Instead of taking fixed indexes for the path elements, base everything
off the index of the found 'scm' path element.
2018-01-09 09:21:01 +01:00
Frank Fesevur ed3a6d0f4d Various improvements as suggested in #110 2017-12-28 00:04:52 +01:00
Dave Wikoff 8caa9ad1da
Merge pull request #112 from felixmosh/master
One-liner install for oh-my-zsh
2017-12-22 11:00:09 -05:00
Felix Mosheev 29434cd76e One liner install for oh-my-zsh 2017-12-21 17:36:23 +02:00
Frank Fesevur ade7ae1595 Add man page 2017-12-03 22:33:45 +01:00
Paul Irish 170159c345
New demo GIF for the readme (#108) 2017-12-01 15:14:49 -08:00
Paul Irish 2ade70e717 readme: changelog bump for 2.0 - breaking change about config. 2017-12-01 14:29:39 -08:00
Paul Irish 4173f3dea4 v2.0.0 2017-12-01 14:27:11 -08:00
Paul Irish 7cf058d1bf readme: changelog bump for 2.0 2017-12-01 14:27:02 -08:00
Paul Irish cdfb1cb05c
readme: refactor Configuration section (#107) 2017-12-01 14:23:41 -08:00
Paul Irish b526edced1
readme: changelog updates 2017-12-01 14:17:33 -08:00
Paul Irish f0bcdd200a
update readme for (gitlab) config (#99) 2017-12-01 13:41:45 -08:00
Frank Fesevur 734517991a Update support for open.default.remote config (#79) 2017-12-01 13:41:32 -08:00
Frank Fesevur d97b7f36aa Fix BATS testing on WSL (#104)
The $openopt resulted in unexpected results during testing
2017-12-01 12:30:50 -08:00
Paul Irish 3a423e11a6
allow command to be run in git repo subdirectory (#105) 2017-12-01 12:18:07 -08:00
Edward Thomson e3ce014bfa Add support for Visual Studio Team Services and Team Foundation Server (#93)
* Parse remotes as URLs or SCP-style paths

Instead of trying to strip on ':' and '/' to simplify a URL, actually
switch based on whether the remote path is a URL ("scheme://host:port/path")
or an SCP-style path (user@host:path) and parse them separately.

This allows us to handle custom ports in HTTP and HTTPS, but ignore
custom ports in an SSH url and HTTP remotes, instead of always upgrading
them to HTTPS.

* Introduce tests for Visual Studio Team Services

Add tests for Visual Studio Team Services (VSTS) and Team Foundation
Server (TFS).  VSTS suggests remote paths in two formats: HTTPS URLs
or SSH URLs (including port number).  TFS is an on-premises product
which - when running as an HTTP endpoint - defaults to port 8080.

* Branch selection in Visual Studio Team Services

VSTS and TFS URLs end in '/_git/RepositoryName` (with 0 or more leading
folders of hierarchy in front of that.)  Detect these from the `_git` in
the penultimate folder of the path.  Append branch information to VSTS
and TFS URLs.

Since VSTS and TFS use a query string to select a branch, instead of
including it in the server path, the `providerBranchRef` for other
services was changed to include the leading `/`, and now the `openurl`
and `providerBranchRef` are simply concatenated, to avoid an incorrect
trailing `/` for the VSTS and TFS branch URLs.

* Issues for Visual Studio Team Services

Provide issue support for VSTS and TFS, modifying the URL from the
`_git` endpoint to the `_workitems` endpoint and appending the `id`
query string.

* README: add VSTS and TFS support
2017-11-30 16:23:52 -08:00
Love F 363d054386 Git styled -h and --issue options (#94) 2017-10-31 16:15:50 -07:00
Frank Fesevur 80cb34169a Add support for WSL (#101) 2017-10-30 16:28:39 -07:00
Paul Irish 07d75b2e1e
add test for bitbucket server (#83)
* add test for bitbucket server
* add branch test for bb server.
* updated assertions from discussion.
* remove 'git/' from test cases
2017-10-27 14:18:02 -07:00
13 changed files with 6411 additions and 153 deletions

33
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,33 @@
name: CI
on:
push:
branches: [master]
pull_request: # run on all PRs, not just PRs to a particular branch
jobs:
basics:
runs-on: ubuntu-latest
steps:
- name: git clone
uses: actions/checkout@v3
with:
fetch-depth: 100
- uses: actions/setup-node@v3
with:
node-version: latest
- run: npm ci
- name: Setup BATS
uses: mig4/setup-bats@v1
with:
bats-version: 0.4.0 # This is the version i have locally. looks like an upgrade is in order, though…
- run: git submodule update --init
name: pull in bats assertion libs
- run: npm run lint
- run: npm run shellcheck
- run: npm run unit

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
node_modules/
sandboxrepo
git-open.1

5
.npmignore Normal file
View file

@ -0,0 +1,5 @@
node_modules/
sandboxrepo
git-open.1
bats-assert
bats-support

View file

@ -1,21 +0,0 @@
language: node_js
node_js: "node"
addons:
apt:
sources:
- debian-sid # Grab ShellCheck from the Debian repo
packages:
- shellcheck
cache:
directories:
- node_modules
before_install:
- git clone --depth 1 https://github.com/sstephenson/bats.git
install:
- npm install
script:
- npm run lint:package
- npm run lint:readme
- npm run lint:editorconfig
- shellcheck git-open
- ./bats/bin/bats test/*.bats

View file

@ -2,17 +2,29 @@
Type `git open` to open the repo website (GitHub, GitLab, Bitbucket) in your browser.
![git open2015-01-24 13_51_18](https://cloud.githubusercontent.com/assets/39191/5889192/244a0b72-a3d0-11e4-8ab9-55fc64228aaa.gif)
![Demo of git open in action](https://user-images.githubusercontent.com/39191/33507513-f60041ae-d6a9-11e7-985c-ab296d6a5b0f.gif)
## Usage
```sh
git open [remote-name] [branch-name]
# Open the page for this branch on the repo website
git open issue
git open --commit
git open -c
# Open the current commit in the repo website
git open --issue
git open -i
# If this branch is named like issue/#123, this will open the corresponding
# issue in the repo website
git open --print
git open -p
# Only print the url at the terminal, but don't open it
```
(`git open` works with these [hosted repo providers](#supported-remote-repositories), `git open issue` currently only works with GitHub)
(`git open` works with these [hosted repo providers](#supported-remote-repositories), `git open --issue` currently only works with GitHub, Visual Studio Team Services and Team Foundation Server)
### Examples
@ -26,9 +38,15 @@ $ git open someremote
$ git open someremote somebranch
# opens https://github.com/PROVIDED_REMOTE_USER/CURRENT_REPO/tree/PROVIDED_BRANCH
$ git open issue
$ git open --issue
# If branches use naming convention of issues/#123,
# opens https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/issues/123
$ git open --print
# prints https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/tree/CURRENT_BRANCH
$ git open --suffix pulls
# opens https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/pulls
```
## Installation
@ -73,10 +91,10 @@ for testing before adding it to your `.zshrc`.
#### [Oh-My-Zsh](http://ohmyz.sh/)
1. `cd ~/.oh-my-zsh/custom/plugins`
1. `git clone https://github.com/paulirish/git-open.git`
1. Add `git-open` to your plugin list - edit `~/.zshrc` and change
`plugins=(...)` to `plugins=(... git-open)`
1. `git clone https://github.com/paulirish/git-open.git $ZSH_CUSTOM/plugins/git-open`
2. Add `git-open` to your plugin list - edit `~/.zshrc` and change
`plugins=(...)` to `plugins=(... git-open)`
3. `source ~/.zshrc`
#### [Zgen](https://github.com/tarjoilija/zgen)
@ -89,6 +107,15 @@ check for updates to the git repository.
`zplug "paulirish/git-open", as:plugin`
### Bash
#### [Oh-My-Bash](https://github.com/ohmybash/oh-my-bash)
1. `git clone https://github.com/paulirish/git-open.git $OSH_CUSTOM/plugins/git-open`
2. Add `git-open` to your plugin list - edit `~/.bashrc` and change
`plugins=(...)` to `plugins=(... git-open)`
3. `source ~/.bashrc`
## Supported remote repositories
git-open can automatically guess the corresponding repository page for remotes
@ -100,29 +127,14 @@ git-open can automatically guess the corresponding repository page for remotes
- GitLab custom hosted (see below)
- bitbucket.org
- Atlassian Bitbucket Server (formerly _Atlassian Stash_)
- Visual Studio Team Services
- Team Foundation Server (on-premises)
- AWS Code Commit
- cnb.cool
### GitLab support
## Configuration
To configure GitLab support you need to set some options.
| option name | description | example |
| ------------------------- | ---------------------------------------------------------- | ------------------ |
| gitopen.gitlab.domain | The (web)domain name that will work for most of the people | gitlab.example.com |
| gitopen.gitlab.ssh.domain | A specific ssh domain name, *if needed* | git.example.com |
| gitopen.gitlab.ssh.port | A specific ssh port, *if needed* | 10022 |
```sh
# use --global to set across all repos, instead of just the local one
git config [--global] gitopen.gitlab.domain [value]
git config [--global] gitopen.gitlab.ssh.domain [value]
git config [--global] gitopen.gitlab.ssh.port [value]
```
If your Gitlab custom hosted is serving `http` you can also specify this:
```sh
# use --global to set across all repos, instead of just the local one
git config [--global] gitopen.gitlab.protocol http
```
See the [man page](git-open.1.md) for more information on how to configure `git-open`.
## Alternative projects
@ -147,12 +159,7 @@ from which this plugin was forked.
Please provide examples of the URLs you are parsing with each PR.
You can run `git-open` in `echo` mode, which doesn't open your browser, but just prints the URL to stdout:
```sh
env BROWSER='echo' ./git-open
```
#### Testing:
### Testing:
You'll need to install [bats](https://github.com/sstephenson/bats#installing-bats-from-source), the Bash automated testing system. It's also available as `brew install bats`
@ -179,10 +186,17 @@ Copyright Jason McCreary & Paul Irish. Licensed under MIT.
## Changelog
- **2017-06-17** - test suite added
- **2016-07-23** - readme -- fix oh-my-zsh install instructions
- **2016-07-22** - 1.1.0, update and add linters for package.json, readme.
Re-publish to NPM.
- **2016-07-11** - Changelog started (readme formatting and installation
instructions updated)
- **2018-12-03** - [2.1.0 shipped](https://github.com/paulirish/git-open/releases/tag/v2.1.0).
- **2017-12-01** - [2.0 shipped](https://github.com/paulirish/git-open/releases/tag/v2.0.0). Breaking change: [Gitlab configuration](https://github.com/paulirish/git-open#configuration) handled differently.
- **2017-12-01** - Configuration for custom remote added
- **2017-11-30** - Support for VSTS Added
- **2017-10-31** - `--issue` and `-h` added
- **2017-10-30** - Configuration for custom domains added
- **2017-10-30** - WSL support added
- **2017-06-16** - Introduced a test suite in BATS
- **2017-06-15** - Entire script rewritten and simplified by @dermagia
- **2016-07-23** - Readme: fix oh-my-zsh install instructions
- **2016-07-22** - 1.1.0 shipped. update and add linters for package.json, readme.
- **2016-07-11** - Readme formatting and installation instructions updated. Changelog started

26
changelog.md Normal file
View file

@ -0,0 +1,26 @@
## [Version 2.1.0](https://github.com/paulirish/git-open/releases/tag/v2.1.0) (2018-12-3)
[Full changelog](https://github.com/paulirish/git-open/compare/v2.0.0...v2.1.0)
### New features
- Support opening current tag / commit: [#130](https://github.com/paulirish/git-open/pull/130)
- Add man page: [#110](https://github.com/paulirish/git-open/pull/110)
- Add support for sshconfig expansion: [#109](https://github.com/paulirish/git-open/pull/109)
- Add support for Bitbucket Server with different root context: [#113](https://github.com/paulirish/git-open/pull/113)
- Add support for AWS Code commit.: [#128](https://github.com/paulirish/git-open/pull/128)
### Bug fixes
- Fix bug with open -i on default VSTS project repo: [`67b72ac`](https://github.com/paulirish/git-open/commit/67b72ac), [`aea6e3e`](https://github.com/paulirish/git-open/commit/aea6e3e)
- Use ls-remote --get-url to get remote url: [`740222b`](https://github.com/paulirish/git-open/commit/740222b)
- Fix shellcheck: [`775361b`](https://github.com/paulirish/git-open/commit/775361b)
- Fix incompatability with bash < 4: [`895240f`](https://github.com/paulirish/git-open/commit/895240f)
- Swap uppercase/lowercase for ssh feature: [`995e915`](https://github.com/paulirish/git-open/commit/995e915) ([#123](https://github.com/paulirish/git-open/issues/123))
- Remove openopt, allow spaces in $BROWSER: [`96c80ff`](https://github.com/paulirish/git-open/commit/96c80ff)
- readme: One liner install for oh-my-zsh: [`29434cd`](https://github.com/paulirish/git-open/commit/29434cd)
- deps: change markdownlint to markdownlint-cli: [`702b8a6`](https://github.com/paulirish/git-open/commit/702b8a6), [`5b815cb`](https://github.com/paulirish/git-open/commit/5b815cb)
---
Generated by [changelog.md](https://github.com/egoist/changelog.md)

318
git-open
View file

@ -1,11 +1,60 @@
#!/usr/bin/env bash
# Opens the GitHub page for a repo/branch in your browser.
# https://github.com/paulirish/git-open/
#
# git open
# git open [remote] [branch]
# Use git-sh-setup, similar to git-rebase
# https://www.kernel.org/pub/software/scm/git/docs/git-sh-setup.html
# https://github.com/git/git/blob/master/git-rebase.sh
# shellcheck disable=SC2034
OPTIONS_STUCKLONG=t
# shellcheck disable=SC2034
OPTIONS_KEEPDASHDASH=
# shellcheck disable=SC2034
OPTIONS_SPEC="\
git open [options]
git open [remote] [branch]
--
Opens the GitHub page for a repo/branch in your browser.
https://github.com/paulirish/git-open/
Available options are
c,commit! open current commit
i,issue! open issues page
s,suffix= append this suffix
f,file= append this file
p,print! just print the url
"
# https://github.com/koalaman/shellcheck/wiki/SC1090
# shellcheck source=/dev/null
SUBDIRECTORY_OK='Yes' . "$(git --exec-path)/git-sh-setup"
# Defaults
is_commit=0
is_issue=0
protocol="https"
print_only=0
suffix_flag=""
file_flag=""
while test $# != 0; do
case "$1" in
--commit) is_commit=1;;
--issue) is_issue=1;;
--suffix=*) suffix_flag="$1";;
--file=*) file_flag="$1";;
--print) print_only=1;;
--) shift; break ;;
esac
shift
done
# parse suffix from suffix=value
IFS='=' read -ra suffix_flag <<< "$suffix_flag"
function join_by { local IFS="$1"; shift; echo "$*"; }
suffix=$(join_by "=" "${suffix_flag[@]:1}")
# parse file from file=value
IFS='=' read -ra file_flag <<< "$file_flag"
file=$(join_by "=" "${file_flag[@]:1}")
# are we in a git repo?
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
@ -13,50 +62,108 @@ if ! git rev-parse --is-inside-work-tree &>/dev/null; then
exit 1
fi
# Defaults
is_issue=0
protocol="https"
# If the first argument is 'issue', we want to load the issue page
if [[ "$1" == 'issue' ]]; then
is_issue=1
# Allow the user to provide other args, aka `git open issue upstream 79`
shift
fi
# choose remote. priority to: provided argument, detected tracked remote, 'origin'
branch_name=$(git name-rev --name-only HEAD 2>/dev/null)
tracked_remote=$(git config "branch.$branch_name.remote")
remote=${1:-$tracked_remote}
# choose remote. priority to: provided argument, default in config, detected tracked remote, 'origin'
branch=${2:-$(git symbolic-ref -q --short HEAD)}
upstream_branch_full_name=$(git config "branch.$branch.merge")
upstream_branch=${upstream_branch_full_name#"refs/heads/"}
tracked_remote=$(git config "branch.$branch.remote")
default_remote=$(git config open.default.remote)
remote=${1:-$default_remote}
remote=${remote:-$tracked_remote}
remote=${remote:-"origin"}
# @TODO ls-remote will also expand "insteadOf" items `giturl=$(git ls-remote --get-url $remote)``
giturl=$(git config --get "remote.${remote}.url")
giturl=$(git ls-remote --get-url "$remote")
if [[ -z "$giturl" ]]; then
echo "Git remote is not set for $remote" 1>&2
exit 1
fi
ssh_config=${ssh_config:-"$HOME/.ssh/config"}
# Resolves an ssh alias defined in ssh_config to it's corresponding hostname
# echos out result, should be used within subshell $( ssh_resolve $host )
# echos out nothing if alias could not be resolved
function ssh_resolve() {
domain="$1"
ssh_found=true
# Filter to only ssh_config lines that start with "Host" or "HostName"
resolved=$(while read -r ssh_line; do
# Split each line by spaces, of the form:
# Host alias [alias...]
# Host regex
# HostName resolved.domain.com
read -r -a ssh_array <<<"${ssh_line}"
ssh_optcode="$(echo "${ssh_array[0]}" | tr '[:lower:]' '[:upper:]')"
if [[ $ssh_optcode == HOST ]]; then
# Host
ssh_found=false
# Iterate through aliases looking for a match
for ssh_index in $(seq 1 $((${#ssh_array[@]} - 1))); do
ssh_host=${ssh_array[$ssh_index]}
# shellcheck disable=SC2053
if [[ $domain == $ssh_host ]]; then
# Found a match, next HostName entry will be returned while matched
ssh_found=true
break
fi
done
elif $ssh_found && [[ $ssh_optcode == HOSTNAME ]]; then
# HostName, but only if ssh_found is true (the last Host entry matched)
# Replace all instances of %h with the Host alias
echo "${ssh_array[1]//%h/$domain}"
fi
done < <(grep -iE "^\\s*Host(Name)?\\s+" "$ssh_config"))
# Take only the last resolved hostname (multiple are overridden)
tail -1 <<<"$resolved"
}
# From git-fetch(5), native protocols:
# ssh://[user@]host.xz[:port]/path/to/repo.git/
# git://host.xz[:port]/path/to/repo.git/
# http[s]://host.xz[:port]/path/to/repo.git/
# ftp[s]://host.xz[:port]/path/to/repo.git/
# [user@]host.xz:path/to/repo.git/ - scp-like but is an alternative to ssh.
# [user@]hostalias:path/to/repo.git/ - handles host aliases defined in ssh_config(5)
# Trim "/" and ".git" from the end of the url
giturl=${giturl%/} giturl=${giturl%.git}
# Determine whether this is a url (https, ssh, git+ssh...) or an scp-style path
if [[ "$giturl" =~ ^[a-z\+]+://.* ]]; then
# Trim URL scheme and possible username
gitprotocol=${giturl%%://*}
uri=${giturl#*://}
uri=${uri#*@}
# Trim before last '@' and protocol (*://) from beginning
uri=${giturl##*@} uri=${uri##*://}
# Split on first '/ to get server name and path
domain=${uri%%/*}
urlpath=${uri#*/}
# If there isn't a protocol, we can assume it's using the scp syntax which uses ':' to seperate the path.
[[ $giturl =~ :// ]] && pathsep='/' || pathsep=':'
# Remove port number from non-http/https protocols (ie, ssh)
if [[ $gitprotocol != 'https' && $gitprotocol != 'http' ]]; then
domain=${domain%:*}
fi
else
# Trim possible username from SSH path
uri=${giturl##*@}
# Seperate the domain and the urlpath on the first {pathsep}. This also removes the gitport from the domain.
domain=${uri%%[:$pathsep]*} urlpath=${uri#*$pathsep}
# Split on first ':' to get server name and path
domain=${uri%%:*}
urlpath=${uri#*:}
# Resolve sshconfig aliases
if [[ -e "$ssh_config" ]]; then
domain_resolv=$(ssh_resolve "$domain")
if [[ -n "$domain_resolv" ]]; then
domain="$domain_resolv"
fi
fi
fi
# Trim "/" from beginning of URL; "/" and ".git" from end of URL
urlpath=${urlpath#/} urlpath=${urlpath%/} urlpath=${urlpath%.git}
# If the URL is provided as "http", preserve that
if [[ $gitprotocol == 'http' ]]; then
protocol='http'
fi
# Allow config options to replace the server or the protocol
openurl="$protocol://$domain"
@ -68,54 +175,149 @@ function getConfig() {
domain=$(getConfig "domain")
protocol=$(getConfig "protocol")
forge=$(getConfig "forge")
# Get current branch
branch=${2:-$(git symbolic-ref -q --short HEAD)}
# Remote ref to open
remote_ref=${upstream_branch:-${branch:-$(git describe --tags --exact-match 2>/dev/null || git rev-parse HEAD)}}
# Split arguments on '/'
IFS='/' pathargs=($urlpath)
IFS='/' read -r -a pathargs <<<"$urlpath"
if (( is_issue )); then
# For issues, take the numbers and preprend 'issues/'
providerBranchRef="issues/${branch//[^0-9]/}"
[[ $remote_ref =~ [0-9]+ ]]
providerBranchRef="/issues/${BASH_REMATCH[0]}"
else
# Make # and % characters url friendly
# github.com/paulirish/git-open/pull/24
branch=${branch//%/%25} branch=${branch//#/%23}
providerBranchRef="tree/$branch"
remote_ref=${remote_ref//%/%25} remote_ref=${remote_ref//#/%23}
if [[ $forge == 'gitea' ]]; then
providerBranchRef="/src/branch/$remote_ref"
else
providerBranchRef="/tree/$remote_ref"
fi
fi
if [[ "$domain" == 'bitbucket.org' ]]; then
# Bitbucket, see https://github.com/paulirish/git-open/issues/80 for why ?at is needed.
providerBranchRef="src?at=$branch"
elif [[ ${pathargs[0]} == 'scm' ]]; then
# Bitbucket server, which starts with 'scm'
# Replace the first element, 'scm', with 'projects'. Keep the first argument, the string 'repos', and finally the rest of the arguments.
pathargs=('projects' ${pathargs[1]} 'repos' "${pathargs[@]:2}")
IFS='/' urlpath="${pathargs[*]}"
providerBranchRef="browse?at=$branch"
fi
providerBranchRef="/src/$remote_ref"
elif [[ "${#pathargs[@]}" -ge 3 && ${pathargs[${#pathargs[@]} - 3]} == 'scm' ]]; then
# Bitbucket server always has /scm/ as the third to last segment in the url path, e.g. /scm/ppp/test-repo.git
# Anything before the 'scm' is part of the server's root context
# If there are other context parts, add them, up to (but not including) the found 'scm'
pathPref=("${pathargs[*]:0:${#pathargs[@]} - 3}")
# Replace the 'scm' element, with 'projects'. Keep the first argument, the string 'repos', and finally the rest of the arguments.
# shellcheck disable=SC2206
pathargs=(${pathPref[@]} 'projects' ${pathargs[${#pathargs[@]} - 2]} 'repos' "${pathargs[@]:${#pathargs[@]} - 1}")
IFS='/' urlpath="${pathargs[*]}"
providerBranchRef="/browse?at=$remote_ref"
elif [[ "$domain" == *"bitbucket"* ]] && [[ $gitprotocol == 'ssh' ]]; then
# bitbucket repo cloned with ssh will not have /scm/ segment in url path
# e.g. /ppp/test-repo.git
# Build the repo url starting with 'projects' and then keep the first argument, the string 'repos', and finally the rest of the arguments.
# shellcheck disable=SC2206
pathargs=('projects' ${pathargs[${#pathargs[@]} - 2]} 'repos' "${pathargs[@]:${#pathargs[@]} - 1}")
IFS='/' urlpath="${pathargs[*]}"
providerBranchRef="/browse?at=$remote_ref"
elif [[ "${#pathargs[@]}" -ge '2' && ${pathargs[${#pathargs[@]} - 2]} == '_git' ]]; then
# Visual Studio Team Services and Team Foundation Server always have /_git/ as the second to last segment in the url path
if (( is_issue )); then
# Switch to workitems, provide work item id if specified
urlpath="${urlpath%%/_git/*}/_workitems"
# Handle case for the default repository url
urlpath="${urlpath#_git\/*}"
providerBranchRef="?id=${remote_ref//[^0-9]/}"
else
# Keep project and repository name, append branch selector.
providerBranchRef="?version=GB$remote_ref"
fi
elif [[ "$domain" =~ amazonaws\.com$ ]]; then
# AWS Code Commit
if (( is_issue )); then
echo "Issue feature does not supported on AWS Code Commit." 1>&2
exit 1
fi
# Take region name from domain.
region=${domain#*.}
region=${region%%.*}
# Replace domain.
# Ex. git-codecommit.us-east-1.amazonaws.com -> us-east-1.console.aws.amazon.com
domain="${region}.console.aws.amazon.com"
# Replace URL path.
# Ex. v1/repos/example -> codecommit/home?region=us-east-1#/repository/example/browse/
urlpath="codecommit/home?region=${region}#/repository/${urlpath##*/}/browse/"
# Replace branch ref.
# Ex. /tree/foobar -> foobar/--/
providerBranchRef="${providerBranchRef##*/}/--/"
elif [[ "$domain" =~ cnb\.cool$ ]]; then
# cnb.cool
# Replace URL path.
# Ex. repos/example -> repos/example/-
urlpath="$urlpath/-"
if [[ $remote_ref = "master" ]]; then
# repos/example/tree/master -> repos/example/-/tree/master
urlpath="$urlpath$providerBranchRef"
fi
fi
openurl="$protocol://$domain/$urlpath"
# simplify URL for master
if [[ $branch != "master" ]]; then
openurl="$openurl/$providerBranchRef"
if (( is_commit )); then
sha=$(git rev-parse HEAD)
openurl="$openurl/commit/$sha"
elif [[ $remote_ref != "master" || "$file" ]]; then
# simplify URL for master
openurl="$openurl$providerBranchRef"
fi
if [ "$file" ]; then
absfile=$(git ls-tree --full-name --name-only "$branch" "$file")
if [[ -z "$absfile" ]]; then
echo "File $file is not in repository" 1>&2
exit 1
fi
openurl="$openurl/$absfile"
fi
if [ "$suffix" ]; then
openurl="$openurl/$suffix"
fi
# get current open browser command
case $( uname -s ) in
Darwin) open='open';;
MINGW*) open='start';;
MSYS*) open='start';;
CYGWIN*) open='cygstart';;
*) open='xdg-open';;
Darwin) open='open';;
MINGW*) open='start';;
MSYS*) open='start';;
CYGWIN*) open='cygstart';;
*) # Try to detect WSL (Windows Subsystem for Linux)
if uname -r | grep -q -i Microsoft; then
open='/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -NoProfile Start'
else
open='xdg-open'
fi;;
esac
# Allow printing the url if BROWSER=echo
if [[ $BROWSER != "echo" ]]; then
exec &>/dev/null
if (( print_only )); then
printf '%s\n' "$openurl"
exit 0
fi
# open it in a browser
${BROWSER:-$open} "$openurl"
if [[ -n "$BROWSER" ]]; then
if [[ -x "$BROWSER" ]]; then
"$BROWSER" "$openurl"
exit $?
fi
if command -v -- "$BROWSER" >/dev/null 2>&1; then
"$BROWSER" "$openurl"
exit $?
fi
fi
"$open" "$openurl"

178
git-open.1.md Normal file
View file

@ -0,0 +1,178 @@
# git-open - Open the repository's website in your browser.
## SYNOPSIS
`git open` [--issue] [--commit] [--suffix some_suffix] [remote-name] [branch-name]
## DESCRIPTION
`git open` opens the repository's website in your browser. The major well known
git hosting services are supported.
## OPTIONS
`-c`, `--commit`
Open the current commit. See `EXAMPLES` for more information.
Only tested with GitHub & GitLab.
`-i`, `--issue`
Open the current issue. When the name of the current branch matches the right pattern,
it will open the webpage with that issue. See `EXAMPLES` for more information.
This only works on GitHub, GitLab, Visual Studio Team Services and Team Foundation Server at the moment.
`-s`, `--suffix` some_suffix
Append the given suffix to the url
`-p`, `--print`
Just print the URL. Do not open it in browser.
`-h`
Show a short help text.
## EXAMPLES
```sh
git open
```
It opens https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/
```sh
git open someremote
```
It opens https://github.com/PROVIDED_REMOTE_USER/CURRENT_REPO/
```sh
git open someremote somebranch
```
It opens https://github.com/PROVIDED_REMOTE_USER/CURRENT_REPO/tree/PROVIDED_BRANCH
```sh
git open --issue
```
If branches use naming convention of `issues/#123`, it opens
https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/issues/123
```sh
git open --suffix pulls
```
It opens the URL https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/pulls
```sh
git open --print
```
It prints the URL https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/
```sh
git open --commit
```
Supposing that the current sha is `2ddc8d4548d0cee3d714dcf0068dbec5b168a9b2`, it opens
https://github.com/TRACKED_REMOTE_USER/CURRENT_REPO/commit/2ddc8d4548d0cee3d714dcf0068dbec5b168a9b2
## SUPPORTED GIT HOSTING SERVICES
git-open can automatically guess the corresponding repository page for remotes
on the following git hosting services:
- github.com
- gist.github.com
- gitlab.com
- GitLab CE/EE (self hosted GitLab, see `CONFIGURATION`)
- bitbucket.org
- Atlassian Bitbucket Server (formerly _Atlassian Stash_)
- Visual Studio Team Services
- Team Foundation Server (on-premises)
## CONFIGURATION
To configure git-open you may need to set some `git config` options.
You can use `--global` to set across all repos, instead of just the current repo.
```sh
git config [--global] option value
```
### Configuring which remote to open
By default, `git open` opens the remote named `origin`. However, if your current branch is remotely-tracking a different remote, that tracked remote will be used.
In some instances, you may want to override this behavior. When you fork a project
and add a remote named `upstream` you often want that upstream to be opened
rather than your fork. To accomplish this, you can set the `open.default.remote` within your project:
```sh
git config open.default.remote upstream
```
This is equivalent to always typing `git open upstream`.
### Gitea options
To configure Gitea support you need to set the following option.
`open.[gitdomain].forge`
The git forge present at the git domain. This only needs to be set for Gitea because it uses another branch URL format.
**Example**
```sh
git config [--global] "open.https://gitea.internal.biz.forge" "gitea"
```
### GitLab options
To configure GitLab support (or other unique hosting situations) you may need to set some options.
`open.[gitdomain].domain`
The (web) domain to open based on the provided git repo domain.
`open.[gitdomain].protocol`
The (web) protocol to open based on the provided git repo domain. Defaults to `https`.
```sh
git config [--global] open.[gitdomain].domain [value]
git config [--global] open.[gitdomain].protocol [value]
```
**Example**
- Your git remote is at `ssh://git@git.internal.biz:7000/XXX/YYY.git`
- Your hosted gitlab is `http://repo.intranet/subpath/XXX/YYY`
```sh
git config [--global] "open.https://git.internal.biz.domain" "repo.intranet/subpath"
git config [--global] "open.https://git.internal.biz.protocol" "http"
```
## DEBUGGING
You can run `git-open` in `echo` mode, which doesn't open your browser, but just prints the URL to stdout:
```sh
env BROWSER='echo' ./git-open
```
## AUTHORS
Jason McCreary did the initial hard work. Paul Irish based his project on his work.
Since then many contributors have submitted great PRs.
## SEE ALSO
git(1), git-remote(1), git-config(1), [Project page](https://github.com/paulirish/git-open)

6
git-open.plugin.sh Executable file
View file

@ -0,0 +1,6 @@
# This plugin is MIT licensed to match the git-open license.
#
# Make git-open easy to install and keep up to date if you're using a
# Bash framework like oh-my-bash.
export PATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )":${PATH}

View file

@ -9,6 +9,7 @@
"MD013": false,
"MD026": false,
"MD033": false,
"MD034": false,
"MD036": false,
"MD041": false
}

5324
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
{
"name": "git-open",
"version": "1.5.0",
"version": "3.1.0",
"description": "Type `git open` to open the GitHub/GitLab/Bitbucket homepage for a repository.",
"author": "Paul Irish (http://paulirish.com/)",
"license": "MIT",
@ -10,7 +10,7 @@
},
"repository": {
"type": "git",
"url": "https://github.com/paulirish/git-open.git"
"url": "git+https://github.com/paulirish/git-open.git"
},
"contributors": [
"Paul Irish (http://paulirish.com/)",
@ -30,18 +30,22 @@
"git-open": "git-open",
"git-home": "git-open"
},
"man": "./git-open.1",
"scripts": {
"lint:editorconfig": "eclint check git-open* readme* .travis.yml",
"lint:package": "pjv --recommendations --warnings",
"lint:readme": "node ./node_modules/markdownlint/lib/markdownlint.js --config markdownlint.json README.md",
"test": "npm run unit && npm run lint:package && npm run lint:readme && npm run lint:editorconfig",
"lint:editorconfig": "eclint check ./git-open *.md *.yml",
"lint:readme": "markdownlint --config markdownlint.json README.md",
"lint:man": "markdownlint --config markdownlint.json git-open.1.md",
"man": "marked-man --version \"git-open $npm_package_version\" --manual \"Git manual\" --section 1 git-open.1.md > git-open.1",
"unit": "bats test/",
"watch": "find . -maxdepth 2 -iname '*bats' -o -iname 'git-open' | entr bats test/"
"shellcheck": "shellcheck ./git-open",
"lint": "npm run lint:readme && npm run lint:man && npm run lint:editorconfig",
"test": "npm run unit && npm run lint",
"watch": "find . -maxdepth 2 -iname '*bats' -o -iname 'git-open' | entr bats test/",
"prepublishOnly": "npm run man && npm run test"
},
"dependencies": {},
"devDependencies": {
"eclint": "^2.1.0",
"markdownlint": "^0.2.0",
"package-json-validator": "^0.6.1"
"markdownlint-cli": "^0.32.0",
"marked-man": "^0.7.0"
}
}

View file

@ -20,6 +20,44 @@ setup() {
assert [ -e "$foldername/.git" ]
}
##
## Help
##
@test "help text" {
run ../git-open -h
assert_output --partial "usage: git open"
}
@test "invalid option" {
run ../git-open --invalid-option
assert_output --partial "error: unknown option \`invalid-option'"
assert_output --partial "usage: git open"
}
##
## Print
##
@test "print url" {
git remote set-url origin "git@github.com:user/repo.git"
git checkout -B "master"
BROWSER="assert_failure" run ../git-open -p
assert_output "https://github.com/user/repo"
}
##
## url handling
##
@test "url: insteadOf handling" {
git config --local url.http://example.com/.insteadOf ex:
git remote set-url origin ex:example.git
git checkout -B master
run ../git-open
assert_output "http://example.com/example"
}
##
## GitHub
##
@ -38,6 +76,38 @@ setup() {
assert_output "https://github.com/user/repo/tree/mybranch"
}
@test "gh: upstream branch" {
git remote set-url origin "git@github.com:user/repo.git"
git remote add upstreamRemote "git@github.com:user/upstream-repo.git"
git checkout -B "mybranch"
git config --local "branch.mybranch.merge" "refs/heads/myupstream/mybranch"
git config --local "branch.mybranch.remote" "upstreamRemote"
run ../git-open
assert_output "https://github.com/user/upstream-repo/tree/myupstream/mybranch"
}
@test "gh: upstream branch from param" {
git remote set-url origin "git@github.com:user/repo.git"
git remote add upstreamRemote "git@github.com:user/upstream-repo.git"
git checkout -B "mybranch"
git config --local "branch.mybranch.merge" "refs/heads/upstreamBranch"
git config --local "branch.mybranch.remote" "upstreamRemote"
git checkout master
run ../git-open upstreamRemote mybranch
assert_output "https://github.com/user/upstream-repo/tree/upstreamBranch"
}
@test "gh: tag" {
git remote set-url origin "git@github.com:user/repo.git"
git tag mytag
echo a > a
git add a
git commit -m a
git checkout mytag
run ../git-open
assert_output "https://github.com/user/repo/tree/mytag"
}
@test "gh: non-origin remote" {
git remote set-url origin "git@github.com:user/repo.git"
git remote add upstream "git@github.com:upstreamorg/repo.git"
@ -74,17 +144,37 @@ setup() {
assert_output "https://github.com/user/repo"
}
@test "gh: git open issue" {
@test "gh: git open --issue" {
# https://github.com/paulirish/git-open/pull/46
git remote set-url origin "github.com:paulirish/git-open.git"
git checkout -B "issues/#12"
run ../git-open "issue"
run ../git-open "--issue"
assert_output "https://github.com/paulirish/git-open/issues/12"
# https://github.com/paulirish/git-open/pull/86
git checkout -B "fix-issue-36"
run ../git-open "issue"
assert_output "https://github.com/paulirish/git-open/issues/36"
git checkout -B "fix-issue-37"
run ../git-open "--issue"
assert_output "https://github.com/paulirish/git-open/issues/37"
git checkout -B "fix-issue-38"
run ../git-open "-i"
assert_output "https://github.com/paulirish/git-open/issues/38"
}
@test "gh: git open --commit" {
git remote set-url origin "github.com:paulirish/git-open.git"
sha=$(git rev-parse HEAD)
run ../git-open "--commit"
assert_output "https://github.com/paulirish/git-open/commit/${sha}"
}
@test "gh: git open --suffix anySuffix" {
run ../git-open "--suffix" "anySuffix"
assert_output "https://github.com/paulirish/git-open/anySuffix"
}
@test "gh: git open --suffix anySuffix?hello=world" {
run ../git-open "--suffix" "anySuffix?hello=world"
assert_output "https://github.com/paulirish/git-open/anySuffix?hello=world"
}
@test "gh: gist" {
@ -93,6 +183,19 @@ setup() {
assert_output "https://gist.github.com/2d84a6db1b41b4020685"
}
@test "gh: --file option" {
run ../git-open -f readme.txt
assert_output "https://github.com/paulirish/git-open/tree/master/readme.txt"
# and now a new file in a subdirectory.
mkdir -p subdir
touch subdir/howdy.txt
git add subdir
git commit -am add-in-howdy
run ../git-open -f subdir/howdy.txt
assert_output "https://github.com/paulirish/git-open/tree/master/subdir/howdy.txt"
}
@test "basic: # and % in branch names are URL encoded" {
# https://github.com/paulirish/git-open/pull/24
git checkout -B "issue-#42"
@ -126,6 +229,140 @@ setup() {
assert_output "https://github.com/paulirish/git-open"
}
@test "basic: https url can contain port" {
git remote set-url origin "https://github.com:99/user/repo.git"
run ../git-open
assert_output "https://github.com:99/user/repo"
}
@test "basic: ssh url has port removed from http url" {
git remote set-url origin "ssh://github.com:22/user/repo.git"
run ../git-open
assert_output "https://github.com/user/repo"
}
@test "basic: http url scheme is preserved" {
git remote set-url origin "http://github.com/user/repo.git"
# ignore any local config like: `url.https://github.com/.insteadof=http://github.com/`
GIT_CONFIG_NOSYSTEM=1 run ../git-open
assert_output "http://github.com/user/repo"
}
@test "basic: open.default.remote configuration" {
git remote set-url origin "git@github.com:paulirish/git-open.git"
git remote add upstream "git@github.com:upstreamorg/repo.git"
git config --local open.default.remote upstream
run ../git-open
assert_output "https://github.com/upstreamorg/repo"
}
##
## SSH config
##
@test "sshconfig: basic" {
create_ssh_sandbox
# Basic
git remote set-url origin "basic:user/repo.git"
run ../git-open
assert_output --partial "https://basic.com/user/repo"
# With git user
git remote set-url origin "git@nouser:user/repo.git"
run ../git-open
assert_output "https://no.user/user/repo"
}
@test "sshconfig: no action on no match" {
create_ssh_sandbox
git remote set-url origin "git@nomatch:user/repo.git"
run ../git-open
assert_output "https://nomatch/user/repo"
# No match due to improper casing
}
@test "sshconfig: check case sensitivity" {
create_ssh_sandbox
# Host and HostName keywords should be case insensitive
# But output URL will be case sensitive
git remote set-url origin "malformed:user/repo.git"
run ../git-open
assert_output "https://MaL.FoRmEd/user/repo"
# SSH aliases (hosts) are case sensitive, this should not match
git remote set-url origin "git@MALFORMED:user/repo.git"
run ../git-open
refute_output "https://MaL.FoRmEd/user/repo"
}
@test "sshconfig: multitarget host" {
create_ssh_sandbox
for i in $(seq 1 3); do
git remote set-url origin "multi$i:user/repo.git"
run ../git-open
assert_output "https://multi.com/user/repo"
done
}
@test "sshconfig: host substitution in hostname" {
create_ssh_sandbox
for i in $(seq 1 3); do
git remote set-url origin "sub$i:user/repo.git"
run ../git-open
assert_output "https://sub$i.multi.com/user/repo"
done
}
@test "sshconfig: host wildcard * matches zero or more chars" {
create_ssh_sandbox
# Normal *
for str in "" "-prod" "-dev"; do
git remote set-url origin "zero$str:user/repo.git"
run ../git-open
assert_output "https://zero.com/user/repo"
done
# * with substitution
for str in "" "-prod" "-dev"; do
git remote set-url origin "subzero$str:user/repo.git"
run ../git-open
assert_output "https://subzero$str.zero/user/repo"
done
}
@test "sshconfig: host wildcard ? matches exactly one char" {
create_ssh_sandbox
# Normal ?
for i in $(seq 1 3); do
git remote set-url origin "one$i:user/repo.git"
run ../git-open
assert_output "https://one.com/user/repo"
done
# Refute invalid match on ?
for str in "" "-test"; do
git remote set-url origin "one:user/repo.git"
run ../git-open
refute_output "https://one$str.com/user/repo"
done
# ? with substitution
for i in $(seq 1 3); do
git remote set-url origin "subone$i:user/repo.git"
run ../git-open
assert_output "https://subone$i.one/user/repo"
done
# Refute invalid match on ? with substitution
for str in "" "-test"; do
git remote set-url origin "subone$str:user/repo.git"
run ../git-open
refute_output "https://subone$str.one/user/repo"
done
# Refute invalid match on ? with substitution
}
@test "sshconfig: overriding host rules" {
create_ssh_sandbox
git remote set-url origin "zero-override:user/repo.git"
run ../git-open
assert_output "https://override.zero.com/user/repo"
}
##
## Bitbucket
@ -137,6 +374,17 @@ setup() {
assert_output --partial "https://bitbucket.org/paulirish/crbug-extension"
}
@test "bitbucket: tag" {
git remote set-url origin "git@bitbucket.org:paulirish/crbug-extension.git"
git tag mytag
echo a > a
git add a
git commit -m a
git checkout mytag
run ../git-open
assert_output "https://bitbucket.org/paulirish/crbug-extension/src/mytag"
}
@test "bitbucket: non-origin remote" {
# https://github.com/paulirish/git-open/pull/4
git remote add bbclone "git@bitbucket.org:rwhitbeck/git-open.git"
@ -150,7 +398,7 @@ setup() {
git checkout -B "devel"
run ../git-open
refute_output --partial "//kisom"
assert_output "https://bitbucket.org/kisom/consbri/src?at=devel"
assert_output "https://bitbucket.org/kisom/consbri/src/devel"
}
@test "bitbucket: open source view with a slash/branch" {
@ -159,9 +407,7 @@ setup() {
git remote set-url origin "https://bitbucket.org/guyzmo/git-repo.git"
git checkout -B "bugfix/conftest_fix"
run ../git-open
assert_output --partial "https://bitbucket.org/guyzmo/git-repo/src"
# BB appears to be fine with both literal or URL-encoded forward slash
assert_output --partial "?at=bugfix/conftest_fix"
assert_output "https://bitbucket.org/guyzmo/git-repo/src/bugfix/conftest_fix"
}
@test "bitbucket: ssh:// clone urls" {
@ -178,19 +424,81 @@ setup() {
refute_output --partial "@"
}
@test "bitbucket server" {
# https://github.com/paulirish/git-open/pull/15
git remote set-url origin "https://user@bitbucket.example.com/scm/ppp/test-repo.git"
@test "bitbucket: Bitbucket Server" {
# https://github.com/paulirish/git-open/issues/77#issuecomment-309044010
git remote set-url origin "https://user@mybb.domain.com/scm/ppp/rrr.git"
run ../git-open
assert_output "https://bitbucket.example.com/projects/ppp/repos/test-repo"
# any of the following are acceptable
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr" ||
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr/browse/?at=master" ||
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr/browse/?at=refs%2Fheads%2Fmaster"
}
@test "bitbucket server branch" {
# https://github.com/paulirish/git-open/pull/15
git remote set-url origin "https://user@bitbucket.example.com/scm/ppp/test-repo.git"
git checkout -B "bb-server"
@test "bitbucket: Bitbucket Server branch" {
# https://github.com/paulirish/git-open/issues/80
git remote set-url origin "https://user@mybb.domain.com/scm/ppp/rrr.git"
git checkout -B "develop"
run ../git-open
assert_output "https://bitbucket.example.com/projects/ppp/repos/test-repo/browse?at=bb-server"
# The following query args work with BB Server:
# at=refs%2Fheads%2Fdevelop, at=develop, at=refs/heads/develop
# However /src/develop does not (unlike bitbucket.org)
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr/browse?at=develop" ||
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr/browse?at=refs%2Fheads%2Fdevelop" ||
assert_output "https://mybb.domain.com/projects/ppp/repos/rrr/browse?at=refs/heads/develop"
refute_output --partial "/src/develop"
}
@test "bitbucket: Bitbucket Server private user repos" {
# https://github.com/paulirish/git-open/pull/83#issuecomment-309968538
git remote set-url origin "https://mybb.domain.com/scm/~first.last/rrr.git"
git checkout -B "develop"
run ../git-open
assert_output "https://mybb.domain.com/projects/~first.last/repos/rrr/browse?at=develop" ||
assert_output "https://mybb.domain.com/projects/~first.last/repos/rrr/browse?at=refs%2Fheads%2Fdevelop" ||
assert_output "https://mybb.domain.com/projects/~first.last/repos/rrr/browse?at=refs/heads/develop"
}
@test "bitbucket: Bitbucket Server with different root context" {
# https://github.com/paulirish/git-open/pull/15
git remote set-url origin "https://user@bitbucket.example.com/git/scm/ppp/test-repo.git"
run ../git-open
assert_output "https://bitbucket.example.com/git/projects/ppp/repos/test-repo" ||
assert_output "https://bitbucket.example.com/git/projects/ppp/repos/test-repo/?at=master" ||
assert_output "https://bitbucket.example.com/git/projects/ppp/repos/test-repo/?at=refs%2Fheads%2Fmaster"
}
@test "bitbucket: Bitbucket Server with different root context with multiple parts" {
# https://github.com/paulirish/git-open/pull/15
git remote set-url origin "https://user@bitbucket.example.com/really/long/root/context/scm/ppp/test-repo.git"
run ../git-open
assert_output "https://bitbucket.example.com/really/long/root/context/projects/ppp/repos/test-repo" ||
assert_output "https://bitbucket.example.com/really/long/root/context/projects/ppp/repos/test-repo/?at=master" ||
assert_output "https://bitbucket.example.com/really/long/root/context/projects/ppp/repos/test-repo/?at=refs%2Fheads%2Fmaster"
}
@test "bitbucket: Bitbucket Server private user repos with different root context" {
# https://github.com/paulirish/git-open/pull/83#issuecomment-309968538
git remote set-url origin "https://mybb.domain.com/root/context/scm/~first.last/rrr.git"
git checkout -B "develop"
run ../git-open
assert_output "https://mybb.domain.com/root/context/projects/~first.last/repos/rrr/browse?at=develop" ||
assert_output "https://mybb.domain.com/root/context/projects/~first.last/repos/rrr/browse?at=refs%2Fheads%2Fdevelop" ||
assert_output "https://mybb.domain.com/root/context/projects/~first.last/repos/rrr/browse?at=refs/heads/develop"
}
@test "bitbucket: Selfhosted Bitbucket Server with ssh:// clone urls" {
# https://github.com/paulirish/git-open/pull/174
git remote set-url origin "ssh://git@bitbucket.domain.com/ppp/rrr.git"
run ../git-open
assert_output "https://bitbucket.domain.com/projects/ppp/repos/rrr"
}
@ -201,7 +509,6 @@ setup() {
@test "gitlab: default ssh origin style" {
# https://github.com/paulirish/git-open/pull/55
git remote set-url origin "git@gitlab.example.com:user/repo"
git config "gitopen.gitlab.domain" "gitlab.example.com"
run ../git-open
assert_output "https://gitlab.example.com/user/repo"
}
@ -209,7 +516,6 @@ setup() {
@test "gitlab: ssh://git@ origin" {
# https://github.com/paulirish/git-open/pull/51
git remote set-url origin "ssh://git@gitlab.domain.com/user/repo"
git config "gitopen.gitlab.domain" "gitlab.domain.com"
run ../git-open
assert_output "https://gitlab.domain.com/user/repo"
refute_output --partial "//user"
@ -242,13 +548,130 @@ setup() {
git remote set-url origin "https://git.example.com:7000/XXX/YYY.git"
run ../git-open
assert_output "https://git.example.com/XXX/YYY"
refute_output --partial ":7000"
assert_output "https://git.example.com:7000/XXX/YYY"
}
@test "gitlab: issue" {
git remote set-url origin "git@gitlab.example.com:user/repo"
git checkout -B "10-bump-up-to-v2.0"
run ../git-open "--issue"
assert_output "https://gitlab.example.com/user/repo/issues/10"
}
##
## Visual Studio Team Services
##
@test "vsts: https url" {
git remote set-url origin "https://gitopen.visualstudio.com/Project/_git/Repository"
run ../git-open
assert_output --partial "https://gitopen.visualstudio.com/Project/_git/Repository"
}
@test "vsts: ssh url" {
git remote add vsts_ssh "ssh://gitopen@gitopen.visualstudio.com:22/Project/_git/Repository"
run ../git-open "vsts_ssh"
assert_output "https://gitopen.visualstudio.com/Project/_git/Repository"
}
@test "vsts: on-premises tfs http url" {
git remote set-url origin "http://tfs.example.com:8080/Project/_git/Repository"
run ../git-open
assert_output --partial "http://tfs.example.com:8080/Project/_git/Repository"
}
@test "vsts: branch" {
git remote set-url origin "ssh://gitopen@gitopen.visualstudio.com:22/_git/Repository"
git checkout -B "mybranch"
run ../git-open
assert_output "https://gitopen.visualstudio.com/_git/Repository?version=GBmybranch"
}
@test "vsts: on-premises tfs branch" {
git remote set-url origin "http://tfs.example.com:8080/Project/Folder/_git/Repository"
git checkout -B "mybranch"
run ../git-open
assert_output "http://tfs.example.com:8080/Project/Folder/_git/Repository?version=GBmybranch"
}
@test "vsts: issue" {
git remote set-url origin "http://tfs.example.com:8080/Project/Folder/_git/Repository"
git checkout -B "bugfix-36"
run ../git-open "--issue"
assert_output "http://tfs.example.com:8080/Project/Folder/_workitems?id=36"
}
@test "vsts: default project repository - issue" {
git remote set-url origin "https://gitopen.visualstudio.com/_git/Project"
git checkout -B "bugfix-36"
run ../git-open "--issue"
assert_output "https://gitopen.visualstudio.com/Project/_workitems?id=36"
}
##
## AWS Code Commit
##
@test "aws: https url" {
git remote set-url origin "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/repo"
git checkout -B "master"
run ../git-open
assert_output "https://us-east-1.console.aws.amazon.com/codecommit/home?region=us-east-1#/repository/repo/browse/"
}
@test "aws: ssh url" {
git remote set-url origin "ssh://git-codecommit.us-east-1.amazonaws.com/v1/repos/repo"
git checkout -B "master"
run ../git-open
assert_output "https://us-east-1.console.aws.amazon.com/codecommit/home?region=us-east-1#/repository/repo/browse/"
}
@test "aws: branch " {
git remote set-url origin "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/repo"
git checkout -B "mybranch"
run ../git-open
assert_output "https://us-east-1.console.aws.amazon.com/codecommit/home?region=us-east-1#/repository/repo/browse/mybranch/--/"
}
@test "aws: issue" {
git remote set-url origin "https://git-codecommit.us-east-1.amazonaws.com/v1/repos/repo"
git checkout -B "issues/#12"
run ../git-open "--issue"
[ "$status" -eq 1 ]
assert_output "Issue feature does not supported on AWS Code Commit."
}
##
## cnb.cool
##
@test "cnb: https url" {
git remote set-url origin "https://cnb.cool/repos/repo"
git checkout -B "master"
run ../git-open
assert_output "https://cnb.cool/repos/repo/-/tree/master"
}
@test "cnb: branch " {
git remote set-url origin "https://cnb.cool/repos/repo"
git checkout -B "mybranch"
run ../git-open
assert_output "https://cnb.cool/repos/repo/-/tree/mybranch"
}
@test "cnb: issue" {
git remote set-url origin "https://cnb.cool/repos/repo"
git checkout -B "issues/10"
run ../git-open "--issue"
assert_output "https://cnb.cool/repos/repo/-/issues/10"
}
teardown() {
cd ..
rm -rf "$foldername"
rm -rf "$ssh_config"
refute [ -e "$ssh_config" ]
unset ssh_config
}
# helper to create a test git sandbox that won't dirty the real repo
@ -274,3 +697,65 @@ function create_git_sandbox() {
git add readme.txt
git commit -m "add file" -q
}
# helper to create test SSH config file
function create_ssh_sandbox() {
export ssh_config=$(mktemp)
refute [ -z "$ssh_config" ]
# Populate ssh config with test data
echo "$ssh_testdata" >$ssh_config
assert [ -e "$ssh_config" ]
}
# Test SSH config data
ssh_testdata="
# Autogenerated test sshconfig for paulirish/git-open BATS tests
# It is safe to delete this file, a new one will be generated each test
Host basic
HostName basic.com
User git
Host nomatch
User git
Host nouser
HostName no.user
host malformed
hOsTnAmE MaL.FoRmEd
User other
# Multiple targets
Host multi1 multi2 multi3
HostName multi.com
User git
Host sub1 sub2 sub3
HostName %h.multi.com
User git
# Wildcard * matching (zero or more characters)
Host zero*
HostName zero.com
User git
Host subzero*
HostName %h.zero
User git
# Wildcard ? matching (exactly one character)
Host one?
HostName one.com
User git
Host subone?
HostName %h.one
User git
# Overrides rule zero*
Host zero-override
HostName override.zero.com
User git
"