From 7223c3ec06a6812ae79bd17afa5389eaa3d00a06 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Thu, 2 Feb 2017 13:30:08 -0800 Subject: [PATCH 1/6] Added Github Enterprise support --- Makefile | 3 ++ bin/git-fork | 75 ++++++++++++++++++++++++++++++++------------- helper/config-value | 11 +++++++ man/git-fork.1 | 64 +++++++++++++++++++++++++++++++++++++- man/git-fork.html | 47 ++++++++++++++++++++++++++-- man/git-fork.md | 38 +++++++++++++++++++++++ 6 files changed, 212 insertions(+), 26 deletions(-) create mode 100644 helper/config-value diff --git a/Makefile b/Makefile index bb18c59de..02d995023 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,9 @@ install: if grep "$(COMMAND)" need_git_commit >/dev/null; then \ cat ./helper/has-git-commit >> $(TEMPFILE); \ fi; \ + if grep "# needed_by: $(COMMAND)" helper/config-value >/dev/null; then \ + cat ./helper/config-value | grep -v "# needed_by:" >> $(TEMPFILE); \ + fi; \ tail -n +2 bin/$(COMMAND) >> $(TEMPFILE); \ cp -f $(TEMPFILE) $(DESTDIR)$(BINPREFIX)/$(COMMAND); \ fi; \ diff --git a/bin/git-fork b/bin/git-fork index 19e8d2e6c..a4d4c17bf 100755 --- a/bin/git-fork +++ b/bin/git-fork @@ -10,42 +10,73 @@ test -z "$url" && url=$(git remote get-url origin 2> /dev/null) && origin=true # validate repo url test -z "$url" && abort "github repo needs to be specified as an argument" -# validate user -echo "Enter your github username" -read user -[ -n "$user" ] || abort "git username required" -echo "Enter github two-factor authentication code (leave blank if not set up)" -read MFA_CODE - # extract owner + project from repo url project=${url##*/} owner=${url%/$project} project=${project%.git} -if [[ $owner == git@* ]]; then - owner=${owner##*:} -else - owner=${owner##*/} -fi +owner=${owner##*[/:]} +# Yes, the following extracts server for both SSH and https references +server=${url##*@} +server=${server##*://} +server=${server%%[/:]*} # validate [ -z "$project" -o -z "$owner" ] && abort "github repo needs to be specified as an argument" +# determine github credentials +user=$(get_config_value "$server.user") +token=$(get_config_value "$server.token") +if [[ $(get_config_value "$server.add-api") == "true" ]]; then + api_server="api.$server" +else + api_server=$server +fi + +if [[ -z "$user" ]]; then + # validate user + echo "Enter your github username" + read user + [ -n "$user" ] || abort "git username required" +fi + +if [[ -z "$token" ]]; then + echo "Enter github password" + read password + echo "Enter github two-factor authentication code (leave blank if not set up)" + read MFA_CODE +fi + +auth_info='' +header_info='' +if [[ -n "$token" ]]; then + header_info="-H \"Authorization: token ${token}\"" +elif [[ -n "$MFA_CODE" ]]; then + auth_info="-u \"$user:$password\"" + header_info="-H \"X-GitHub-OTP: $MFA_CODE\"" +elif [[ -n "$password" ]]; then + auth_info="-u \"$user:$password\"" +else + echo "No login credentials specified." + exit 1 +fi + # create fork -curl -qs \ - -X POST \ - -u "$user" \ - -H "X-GitHub-OTP: $MFA_CODE" \ - "https://api.github.com/repos/$owner/$project/forks" +IFS="'" cmd="curl -qs -X POST $auth_info $header_info https://$api_server/repos/$owner/$project/forks" +eval $cmd >/dev/null [ $? = 0 ] || abort "fork failed" -echo "Add GitHub remote branch via SSH (you will be prompted to verify the server's credentials)? (y/n)" -read use_ssh +use_ssh=$(get_config_value "$server.use-ssh") +if [[ -z "$use_ssh" ]]; then + echo "Add GitHub remote branch via SSH (you will be prompted to verify the server's credentials)? (y/n)" + read use_ssh +fi + # Check if user has ssh configured with GitHub -if [ -n "$use_ssh" ] && ssh -T git@github.com 2>&1 | grep -qi 'success'; then - remote_prefix="git@github.com:" +if [ -n "$use_ssh" ] && ssh -T git@$server 2>&1 | grep -qi 'success'; then + remote_prefix="git@$server:" else - remote_prefix="https://github.com/" + remote_prefix="https://$server/" fi if [ "$origin" = true ]; then diff --git a/helper/config-value b/helper/config-value new file mode 100644 index 000000000..6923919e1 --- /dev/null +++ b/helper/config-value @@ -0,0 +1,11 @@ +# needed_by: git-fork + +get_config_value() { + echo $(git config git-extras.$1) +} + +# set_config_value "key" "value" "global|system" (global or system not required) +set_config_value() { + $(git config ${3+--$3} git-extras.$1 $2) + echo $? +} \ No newline at end of file diff --git a/man/git-fork.1 b/man/git-fork.1 index e3c40685e..addc9a2e1 100644 --- a/man/git-fork.1 +++ b/man/git-fork.1 @@ -1,7 +1,7 @@ .\" generated with Ronn/v0.7.3 .\" http://github.com/rtomayko/ronn/tree/0.7.3 . -.TH "GIT\-FORK" "1" "August 2016" "" "Git Extras" +.TH "GIT\-FORK" "1" "February 2017" "" "" . .SH "NAME" \fBgit\-fork\fR \- Fork a repo on github @@ -40,7 +40,66 @@ adds the forked repo as a remote called \fBorigin\fR .P Remotes will use ssh if you have it configured with GitHub, if not, https will be used\. . +.P +Your Github settings can not be saved as git config values instead of specifying them each time\. To enable this you need to execute a few git config commands like the following\. +. +.IP "" 4 +. +.nf + +$ git config \-\-global git\-extras\.github\.com\.user greatcoder99 +. +.fi +. +.IP "" 0 +. +.P +Assuming that your username is \'greatcoder99\'\. All the configuration values are prefixed with \'git\-extras\.\' followed by server hostname and then finally by the variable name (defined below)\. +. +.P +In addition, other Github instances may be used other than just github\.com\. So if you have a Github Enterprise instance, then using that hostname instead of github\.com will work as expected\. +. +.P +Variables that are currently supported: +. +.IP "" 4 +. +.nf + +user: The username that the Github instance knows you as + +token: The personal access token that has been generated to allow + password\-less access to the API\. + +add\-api: In most cases this should be set to true\. This adds the \'api\' + hostname to the repo location (i\.e\. github\.com becomes api\.github\.com) + to access the Github API\. The time you would not set this is when + your API hostname is the same as Github instance hostname\. + +use\-ssh: Set to true in order to set the upstream remote reference + to use SSH instead of https\. +. +.fi +. +.IP "" 0 +. .SH "EXAMPLE" +Create settings to prevent answering questions: +. +.IP "" 4 +. +.nf + +$ git config \-\-global git\-extras\.github\.com\.user bigdog +$ git config \-\-global git\-extras\.github\.com\.token d149feb47\.\.\.\. +$ git config \-\-global git\-extras\.github\.com\.add\-api true +$ git config \-\-global git\-extras\.github\.com\.use\-ssl true +. +.fi +. +.IP "" 0 +. +.P Fork expect\.js: . .IP "" 4 @@ -102,6 +161,9 @@ $ git fork .SH "AUTHOR" Written by Andrew Griffiths <\fImail@andrewgriffithsonline\.com\fR> . +.P +Github Enterprise support and settings by Gerard Hickey <\fIhickey@kinetic\-compute\.com\fR> +. .SH "REPORTING BUGS" <\fIhttps://github\.com/tj/git\-extras/issues\fR> . diff --git a/man/git-fork.html b/man/git-fork.html index 06b5b4443..93b1327c5 100644 --- a/man/git-fork.html +++ b/man/git-fork.html @@ -64,7 +64,7 @@
  1. git-fork(1)
  2. -
  3. Git Extras
  4. +
  5. git-fork(1)
@@ -99,8 +99,47 @@

DESCRIPTION

Remotes will use ssh if you have it configured with GitHub, if not, https will be used.

+

Your Github settings can not be saved as git config values instead of + specifying them each time. To enable this you need to execute a few git + config commands like the following.

+ +
$ git config --global git-extras.github.com.user greatcoder99
+
+ +

Assuming that your username is 'greatcoder99'. All the configuration + values are prefixed with 'git-extras.' followed by server hostname and + then finally by the variable name (defined below).

+ +

In addition, other Github instances may be used other than just + github.com. So if you have a Github Enterprise instance, then using that + hostname instead of github.com will work as expected.

+ +

Variables that are currently supported:

+ +
user: The username that the Github instance knows you as
+
+token: The personal access token that has been generated to allow
+    password-less access to the API.
+
+add-api: In most cases this should be set to true. This adds the 'api'
+    hostname to the repo location (i.e. github.com becomes api.github.com)
+    to access the Github API. The time you would not set this is when
+    your API hostname is the same as Github instance hostname.
+
+use-ssh: Set to true in order to set the upstream remote reference
+    to use SSH instead of https.
+
+

EXAMPLE

+

Create settings to prevent answering questions:

+ +
$ git config --global git-extras.github.com.user bigdog
+$ git config --global git-extras.github.com.token d149feb47....
+$ git config --global git-extras.github.com.add-api true
+$ git config --global git-extras.github.com.use-ssl true
+
+

Fork expect.js:

$ git fork https://github.com/LearnBoost/expect.js
@@ -130,7 +169,9 @@ 

EXAMPLE

AUTHOR

-

Written by Andrew Griffiths <mail@andrewgriffithsonline.com>

+

Written by Andrew Griffiths <mail@andrewgriffithsonline.com>

+ +

Github Enterprise support and settings by Gerard Hickey <hickey@kinetic-compute.com>

REPORTING BUGS

@@ -143,7 +184,7 @@

SEE ALSO

  1. -
  2. August 2016
  3. +
  4. February 2017
  5. git-fork(1)
diff --git a/man/git-fork.md b/man/git-fork.md index 890c5d963..aca4a0eb2 100644 --- a/man/git-fork.md +++ b/man/git-fork.md @@ -21,8 +21,44 @@ git-fork(1) -- Fork a repo on github Remotes will use ssh if you have it configured with GitHub, if not, https will be used. + Your Github settings can not be saved as git config values instead of + specifying them each time. To enable this you need to execute a few git + config commands like the following. + + $ git config --global git-extras.github.com.user greatcoder99 + + Assuming that your username is 'greatcoder99'. All the configuration + values are prefixed with 'git-extras.' followed by server hostname and + then finally by the variable name (defined below). + + In addition, other Github instances may be used other than just + github.com. So if you have a Github Enterprise instance, then using that + hostname instead of github.com will work as expected. + + Variables that are currently supported: + + user: The username that the Github instance knows you as + + token: The personal access token that has been generated to allow + password-less access to the API. + + add-api: In most cases this should be set to true. This adds the 'api' + hostname to the repo location (i.e. github.com becomes api.github.com) + to access the Github API. The time you would not set this is when + your API hostname is the same as Github instance hostname. + + use-ssh: Set to true in order to set the upstream remote reference + to use SSH instead of https. + ## EXAMPLE + Create settings to prevent answering questions: + + $ git config --global git-extras.github.com.user bigdog + $ git config --global git-extras.github.com.token d149feb47.... + $ git config --global git-extras.github.com.add-api true + $ git config --global git-extras.github.com.use-ssl true + Fork expect.js: $ git fork https://github.com/LearnBoost/expect.js @@ -51,6 +87,8 @@ git-fork(1) -- Fork a repo on github Written by Andrew Griffiths <> +Github Enterprise support and settings by Gerard Hickey <> + ## REPORTING BUGS <> From 4f99dbcaabcba6c4c21abb07295d4ef952d1303b Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Thu, 2 Feb 2017 16:02:53 -0800 Subject: [PATCH 2/6] Fixed API prefix for Github Enterprise --- bin/git-fork | 12 +++++++++++- man/git-fork.1 | 5 +++++ man/git-fork.html | 9 +++++++-- man/git-fork.md | 5 +++++ 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/bin/git-fork b/bin/git-fork index a4d4c17bf..d0c29b5b2 100755 --- a/bin/git-fork +++ b/bin/git-fork @@ -31,6 +31,10 @@ if [[ $(get_config_value "$server.add-api") == "true" ]]; then else api_server=$server fi +# retrieve the API prefix and clean it up (i.e. "api/v3/") +api_prefix="$(get_config_value "$server.api-prefix")/" +api_prefix=${api_prefix#/} +api_prefix=${api_prefix/%\/\//\/} if [[ -z "$user" ]]; then # validate user @@ -61,7 +65,7 @@ else fi # create fork -IFS="'" cmd="curl -qs -X POST $auth_info $header_info https://$api_server/repos/$owner/$project/forks" +IFS="'" cmd="curl -qs -X POST $auth_info $header_info https://$api_server/${api_prefix}repos/$owner/$project/forks" eval $cmd >/dev/null [ $? = 0 ] || abort "fork failed" @@ -86,6 +90,12 @@ if [ "$origin" = true ]; then else # clone forked repo into current dir git clone "${remote_prefix}${user}/${project}.git" "$project" + until [[ -d "$project" ]]; do + echo "Github is being slow today. Waiting 10 secs to attempt clone." + sleep 10 + git clone "${remote_prefix}${user}/${project}.git" "$project" + done + # add reference to origin fork so can merge in upstream changes cd "$project" git remote add upstream "${remote_prefix}${owner}/${project}.git" diff --git a/man/git-fork.1 b/man/git-fork.1 index addc9a2e1..da48aaa45 100644 --- a/man/git-fork.1 +++ b/man/git-fork.1 @@ -76,6 +76,11 @@ add\-api: In most cases this should be set to true\. This adds the \'api\' to access the Github API\. The time you would not set this is when your API hostname is the same as Github instance hostname\. +api\-prefix: Github Enterprise much of the time uses "/api/v3/" as a + entry point to the API\. Regular Github access does not need to + have a prefix specified\. Consult your Github administrator for + the correct prefix to use\. + use\-ssh: Set to true in order to set the upstream remote reference to use SSH instead of https\. . diff --git a/man/git-fork.html b/man/git-fork.html index 93b1327c5..4394962b0 100644 --- a/man/git-fork.html +++ b/man/git-fork.html @@ -126,6 +126,11 @@

DESCRIPTION

to access the Github API. The time you would not set this is when your API hostname is the same as Github instance hostname. +api-prefix: Github Enterprise much of the time uses "/api/v3/" as a + entry point to the API. Regular Github access does not need to + have a prefix specified. Consult your Github administrator for + the correct prefix to use. + use-ssh: Set to true in order to set the upstream remote reference to use SSH instead of https.
@@ -169,9 +174,9 @@

EXAMPLE

AUTHOR

-

Written by Andrew Griffiths <mail@andrewgriffithsonline.com>

+

Written by Andrew Griffiths <mail@andrewgriffithsonline.com>

-

Github Enterprise support and settings by Gerard Hickey <hickey@kinetic-compute.com>

+

Github Enterprise support and settings by Gerard Hickey <hickey@kinetic-compute.com>

REPORTING BUGS

diff --git a/man/git-fork.md b/man/git-fork.md index aca4a0eb2..9ebffcc3e 100644 --- a/man/git-fork.md +++ b/man/git-fork.md @@ -47,6 +47,11 @@ git-fork(1) -- Fork a repo on github to access the Github API. The time you would not set this is when your API hostname is the same as Github instance hostname. + api-prefix: Github Enterprise much of the time uses "/api/v3/" as a + entry point to the API. Regular Github access does not need to + have a prefix specified. Consult your Github administrator for + the correct prefix to use. + use-ssh: Set to true in order to set the upstream remote reference to use SSH instead of https. From 1c3621acc38fd7b1be71a77bd0fe15983cc88f47 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Fri, 3 Feb 2017 19:33:33 -0800 Subject: [PATCH 3/6] Squelch error when cloning and add timeout after 1 min on clone failures --- bin/git-fork | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/bin/git-fork b/bin/git-fork index d0c29b5b2..ef139f850 100755 --- a/bin/git-fork +++ b/bin/git-fork @@ -66,7 +66,7 @@ fi # create fork IFS="'" cmd="curl -qs -X POST $auth_info $header_info https://$api_server/${api_prefix}repos/$owner/$project/forks" -eval $cmd >/dev/null +eval $cmd >/dev/null [ $? = 0 ] || abort "fork failed" @@ -89,15 +89,29 @@ if [ "$origin" = true ]; then git fetch origin else # clone forked repo into current dir - git clone "${remote_prefix}${user}/${project}.git" "$project" - until [[ -d "$project" ]]; do - echo "Github is being slow today. Waiting 10 secs to attempt clone." - sleep 10 - git clone "${remote_prefix}${user}/${project}.git" "$project" - done - - # add reference to origin fork so can merge in upstream changes - cd "$project" - git remote add upstream "${remote_prefix}${owner}/${project}.git" - git fetch upstream + git clone "${remote_prefix}${user}/${project}.git" "$project" 2>/dev/null + + # Check to make sure we cloned the repo. Backoff exponetially and try again + timeout=( 2 2 2 6 6 6 20 20 ) + total_wait=0 + until [[ (( "$total_wait" > 60 )) || -d "$project" ]]; do + echo "Github is being slow today. Waiting $timeout secs to attempt clone." + sleep ${timeout[0]} + total_wait=$(expr $total_wait + ${timeout[0]}) + # drop the first element and prepare to wait the next time interval + unset timeout[0] + timeout=( ${timeout[@]} ) + + git clone "${remote_prefix}${user}/${project}.git" "$project" 2>/dev/null + done + + if [[ -d "$proejct" ]]; then + # add reference to origin fork so can merge in upstream changes + cd "$project" + git remote add upstream "${remote_prefix}${owner}/${project}.git" + git fetch upstream + else + echo "Github did not fork within 60 seconds or issue cloning repo." + exit 1 + fi fi From a588462265727c66d89ad474569d60bdd8a0f3c3 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Fri, 3 Feb 2017 19:35:07 -0800 Subject: [PATCH 4/6] Removed request for password and allow curl to capture it --- bin/git-fork | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/bin/git-fork b/bin/git-fork index ef139f850..8cc6b22aa 100755 --- a/bin/git-fork +++ b/bin/git-fork @@ -44,8 +44,6 @@ if [[ -z "$user" ]]; then fi if [[ -z "$token" ]]; then - echo "Enter github password" - read password echo "Enter github two-factor authentication code (leave blank if not set up)" read MFA_CODE fi @@ -55,10 +53,10 @@ header_info='' if [[ -n "$token" ]]; then header_info="-H \"Authorization: token ${token}\"" elif [[ -n "$MFA_CODE" ]]; then - auth_info="-u \"$user:$password\"" + auth_info="-u \"$user\"" header_info="-H \"X-GitHub-OTP: $MFA_CODE\"" elif [[ -n "$password" ]]; then - auth_info="-u \"$user:$password\"" + auth_info="-u \"$user\"" else echo "No login credentials specified." exit 1 From 7867f0269b818c25b78ef3032e692cefebeeedd1 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Fri, 3 Feb 2017 20:06:48 -0800 Subject: [PATCH 5/6] Added better failure mode response --- bin/git-fork | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/bin/git-fork b/bin/git-fork index 8cc6b22aa..f8ffed0aa 100755 --- a/bin/git-fork +++ b/bin/git-fork @@ -64,9 +64,9 @@ fi # create fork IFS="'" cmd="curl -qs -X POST $auth_info $header_info https://$api_server/${api_prefix}repos/$owner/$project/forks" -eval $cmd >/dev/null +eval $cmd | grep "message" >/dev/null -[ $? = 0 ] || abort "fork failed" +[ $? = 0 ] && abort "fork failed" use_ssh=$(get_config_value "$server.use-ssh") if [[ -z "$use_ssh" ]]; then @@ -103,10 +103,11 @@ else git clone "${remote_prefix}${user}/${project}.git" "$project" 2>/dev/null done - if [[ -d "$proejct" ]]; then + if [[ -d "$project" ]]; then # add reference to origin fork so can merge in upstream changes cd "$project" - git remote add upstream "${remote_prefix}${owner}/${project}.git" + git remote add upstream "${remote_prefix}${owner}/${project}.git" 2>/dev/null + [[ $? > 0 ]] && echo "WARN: upstream reference already exists" git fetch upstream else echo "Github did not fork within 60 seconds or issue cloning repo." From f8dd7ed4f503adcbae0deb37c4b5f06147969325 Mon Sep 17 00:00:00 2001 From: Gerard Hickey Date: Sun, 2 Apr 2017 07:34:57 +0200 Subject: [PATCH 6/6] Fixed wording in documentation --- man/git-fork.1 | 2 +- man/git-fork.html | 2 +- man/git-fork.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/man/git-fork.1 b/man/git-fork.1 index da48aaa45..99f569201 100644 --- a/man/git-fork.1 +++ b/man/git-fork.1 @@ -41,7 +41,7 @@ adds the forked repo as a remote called \fBorigin\fR Remotes will use ssh if you have it configured with GitHub, if not, https will be used\. . .P -Your Github settings can not be saved as git config values instead of specifying them each time\. To enable this you need to execute a few git config commands like the following\. +Your Github settings can now be saved as git config values instead of specifying them each time\. To enable this you need to execute a few git config commands like the following\. . .IP "" 4 . diff --git a/man/git-fork.html b/man/git-fork.html index 4394962b0..801442bc2 100644 --- a/man/git-fork.html +++ b/man/git-fork.html @@ -99,7 +99,7 @@

DESCRIPTION

Remotes will use ssh if you have it configured with GitHub, if not, https will be used.

-

Your Github settings can not be saved as git config values instead of +

Your Github settings can now be saved as git config values instead of specifying them each time. To enable this you need to execute a few git config commands like the following.

diff --git a/man/git-fork.md b/man/git-fork.md index 9ebffcc3e..bbb006073 100644 --- a/man/git-fork.md +++ b/man/git-fork.md @@ -21,7 +21,7 @@ git-fork(1) -- Fork a repo on github Remotes will use ssh if you have it configured with GitHub, if not, https will be used. - Your Github settings can not be saved as git config values instead of + Your Github settings can now be saved as git config values instead of specifying them each time. To enable this you need to execute a few git config commands like the following.