提交 7b2311e0 编写于 作者: M Mislav Marohnić

Merge remote-tracking branch 'origin/master' into commentchar-auto

# enforce correct line endings for shell and batch files.
*.sh text eol=lf
script/* text eol=lf
script/*.bat text eol=crlf
......@@ -5,7 +5,8 @@ before_install:
- export PATH=~/bin:"$PATH"
language: go
go:
- 1.8.1
- 1.8.x
- 1.9.x
script: make test-all
install: script/bootstrap
after_success: script/publish-release
......
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at opensource+hub@github.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
......@@ -33,6 +33,13 @@ git version 1.7.6
hub version 2.2.3
```
If you want to get access to new `hub` features earlier and help with its
development by reporting bugs, you can install the prerelease version:
``` sh
$ brew install --devel hub
```
#### Chocolatey
`hub` can be installed through [Chocolatey](https://chocolatey.org/) on Windows.
......@@ -135,8 +142,8 @@ New-Item -Type file -Force $PROFILE
### Shell tab-completion
hub repository contains tab-completion scripts for bash and zsh. These scripts
complement existing completion scripts that ship with git.
hub repository contains tab-completion scripts for bash, zsh and fish.
These scripts complement existing completion scripts that ship with git.
[Installation instructions](etc)
......
......@@ -105,7 +105,7 @@ func New(cmd string) *Cmd {
}
func NewWithArray(cmd []string) *Cmd {
return &Cmd{Name: cmd[0], Args: cmd[1:]}
return &Cmd{Name: cmd[0], Args: cmd[1:], Stdin: os.Stdin, Stdout: os.Stdout, Stderr: os.Stderr}
}
func verboseLog(cmd *Cmd) {
......
......@@ -47,13 +47,13 @@ func clone(command *Command, args *Args) {
func transformCloneArgs(args *Args) {
isSSH := parseClonePrivateFlag(args)
hasValueRegxp := regexp.MustCompile("^(--(upload-pack|template|depth|origin|branch|reference|name)|-[ubo])$")
hasValueRegexp := regexp.MustCompile("^(--(upload-pack|template|depth|origin|branch|reference|name)|-[ubo])$")
nameWithOwnerRegexp := regexp.MustCompile(NameWithOwnerRe)
for i := 0; i < args.ParamsSize(); i++ {
a := args.Params[i]
if strings.HasPrefix(a, "-") {
if hasValueRegxp.MatchString(a) {
if hasValueRegexp.MatchString(a) {
i++
}
} else {
......
......@@ -34,12 +34,12 @@ func init() {
func fetch(command *Command, args *Args) {
if !args.IsParamsEmpty() {
err := tranformFetchArgs(args)
err := transformFetchArgs(args)
utils.Check(err)
}
}
func tranformFetchArgs(args *Args) error {
func transformFetchArgs(args *Args) error {
names := parseRemoteNames(args)
localRepo, err := github.LocalRepo()
......@@ -61,7 +61,7 @@ func tranformFetchArgs(args *Args) error {
continue
}
projects[project] = repo.Private
projects[project] = repo.Private || repo.Permissions.Push
}
}
}
......
......@@ -102,8 +102,22 @@ func fork(cmd *Command, args *Args) {
args.NoForward()
if !flagForkNoRemote {
originURL := originRemote.URL.String()
url := forkProject.GitURL("", "", true)
// Check to see if the remote already exists and points to the fork.
currentRemote, err := localRepo.RemoteByName(newRemoteName)
if err == nil {
currentProject, err := currentRemote.Project()
if err == nil {
if currentProject.SameAs(forkProject) {
ui.Printf("existing remote: %s\n", newRemoteName)
return
}
}
}
args.Before("git", "remote", "add", "-f", newRemoteName, originURL)
args.Before("git", "remote", "set-url", newRemoteName, url)
......
......@@ -50,13 +50,13 @@ func transformInitArgs(args *Args) error {
var err error
dirToInit := "."
hasValueRegxp := regexp.MustCompile("^--(template|separate-git-dir|shared)$")
hasValueRegexp := regexp.MustCompile("^--(template|separate-git-dir|shared)$")
// Find the first argument that isn't related to any of the init flags.
// We assume this is the optional `directory` argument to git init.
for i := 0; i < args.ParamsSize(); i++ {
arg := args.Params[i]
if hasValueRegxp.MatchString(arg) {
if hasValueRegexp.MatchString(arg) {
i++
} else if !strings.HasPrefix(arg, "-") {
dirToInit = arg
......
......@@ -17,7 +17,7 @@ import (
var cmdPullRequest = &Command{
Run: pullRequest,
Usage: `
pull-request [-foc] [-b <BASE>] [-h <HEAD>] [-r <REVIEWERS> ] [-a <ASSIGNEES>] [-M <MILESTONE>] [-l <LABELS>]
pull-request [-focp] [-b <BASE>] [-h <HEAD>] [-r <REVIEWERS> ] [-a <ASSIGNEES>] [-M <MILESTONE>] [-l <LABELS>]
pull-request -m <MESSAGE>
pull-request -F <FILE> [--edit]
pull-request -i <ISSUE>
......@@ -370,7 +370,19 @@ of text is the title and the rest is the description.`, fullBase, fullHead)
}
if len(flagPullRequestReviewers) > 0 {
err = client.RequestReview(baseProject, pr.Number, map[string]interface{}{"reviewers": flagPullRequestReviewers})
userReviewers := []string{}
teamReviewers := []string{}
for _, reviewer := range flagPullRequestReviewers {
if strings.Contains(reviewer, "/") {
teamReviewers = append(teamReviewers, strings.SplitN(reviewer, "/", 2)[1])
} else {
userReviewers = append(userReviewers, reviewer)
}
}
err = client.RequestReview(baseProject, pr.Number, map[string]interface{}{
"reviewers": userReviewers,
"team_reviewers": teamReviewers,
})
utils.Check(err)
}
}
......
......@@ -115,7 +115,7 @@ hub(1), git-tag(1)
Run: downloadRelease,
}
cmdDeleteRelase = &Command{
cmdDeleteRelease = &Command{
Key: "delete",
Run: deleteRelease,
}
......@@ -164,7 +164,7 @@ func init() {
cmdRelease.Use(cmdCreateRelease)
cmdRelease.Use(cmdEditRelease)
cmdRelease.Use(cmdDownloadRelease)
cmdRelease.Use(cmdDeleteRelase)
cmdRelease.Use(cmdDeleteRelease)
CmdRunner.Use(cmdRelease)
}
......
......@@ -6,8 +6,8 @@ if ! declare -F _git > /dev/null && declare -F _completion_loader > /dev/null; t
_completion_loader git
fi
# Check that git tab completion is available
if declare -F _git > /dev/null; then
# Check that git tab completion is available and we haven't already set up completion
if declare -F _git > /dev/null && ! declare -F __git_list_all_commands_without_hub > /dev/null; then
# Duplicate and rename the 'list_all_commands' function
eval "$(declare -f __git_list_all_commands | \
sed 's/__git_list_all_commands/__git_list_all_commands_without_hub/')"
......
......@@ -35,7 +35,10 @@ Feature: hub fetch
Scenario: Creates new remote
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles') { json :private => false }
get('/repos/mislav/dotfiles') {
json :private => false,
:permissions => { :push => false }
}
"""
When I successfully run `hub fetch mislav`
Then "git fetch mislav" should be run
......@@ -72,6 +75,19 @@ Feature: hub fetch
And the url for "mislav" should be "git@github.com:mislav/dotfiles.git"
And there should be no output
Scenario: Writeable repo
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles') {
json :private => false,
:permissions => { :push => true }
}
"""
When I successfully run `hub fetch mislav`
Then "git fetch mislav" should be run
And the url for "mislav" should be "git@github.com:mislav/dotfiles.git"
And there should be no output
Scenario: Fetch with options
Given the GitHub API server:
"""
......
......@@ -121,7 +121,7 @@ Feature: hub fork
"""
And there should be no "mislav" remote
Scenario: Related fork already exists
Scenario: Related fork already exists
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles') {
......@@ -130,8 +130,64 @@ Scenario: Related fork already exists
"""
When I run `hub fork`
Then the exit status should be 0
Then the stdout should contain exactly:
"""
new remote: mislav\n
"""
And the url for "mislav" should be "git@github.com:mislav/dotfiles.git"
Scenario: Unrelated remote already exists
Given the "mislav" remote has url "git@github.com:mislav/unrelated.git"
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles', :host_name => 'api.github.com') { 404 }
post('/repos/evilchelu/dotfiles/forks', :host_name => 'api.github.com') {
assert :organization => nil
status 202
json :name => 'dotfiles', :owner => { :login => 'mislav' }
}
"""
When I run `hub fork`
Then the exit status should be 128
And the stderr should contain exactly:
"""
fatal: remote mislav already exists.\n
"""
And the url for "mislav" should be "git@github.com:mislav/unrelated.git"
Scenario: Related fork and related remote already exist
Given the "mislav" remote has url "git@github.com:mislav/dotfiles.git"
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles') {
json :parent => { :html_url => 'https://github.com/EvilChelu/Dotfiles' }
}
"""
When I run `hub fork`
Then the exit status should be 0
And the stdout should contain exactly:
"""
existing remote: mislav\n
"""
And the url for "mislav" should be "git@github.com:mislav/dotfiles.git"
Scenario: Related fork and related remote, but with differing protocol, already exist
Given the "mislav" remote has url "https://github.com/mislav/dotfiles.git"
Given the GitHub API server:
"""
get('/repos/mislav/dotfiles') {
json :parent => { :html_url => 'https://github.com/EvilChelu/Dotfiles' }
}
"""
When I run `hub fork`
Then the exit status should be 0
And the stdout should contain exactly:
"""
existing remote: mislav\n
"""
And the url for "mislav" should be "https://github.com/mislav/dotfiles.git"
Scenario: Invalid OAuth token
Given the GitHub API server:
"""
......
......@@ -743,13 +743,14 @@ BODY
json :html_url => "the://url", :number => 1234
}
post('/repos/mislav/coral/pulls/1234/requested_reviewers') {
halt 415 unless request.accept?('application/vnd.github.black-cat-preview+json')
halt 415 unless request.accept?('application/vnd.github.thor-preview+json')
assert :reviewers => ["mislav", "josh", "pcorpet"]
assert :team_reviewers => ["robots", "js"]
status 201
json :html_url => "the://url"
}
"""
When I successfully run `hub pull-request -m hereyougo -r mislav,josh -rpcorpet`
When I successfully run `hub pull-request -m hereyougo -r mislav,josh -rgithub/robots -rpcorpet -r github/js`
Then the output should contain exactly "the://url\n"
Scenario: Pull request with milestone
......
......@@ -94,6 +94,59 @@ Feature: hub release
v1.0.2\n
"""
Scenario: Fetch releases across multiple pages
Given the GitHub API server:
"""
get('/repos/mislav/will_paginate/releases') {
assert :per_page => "100", :page => :no
response.headers["Link"] = %(<https://api.github.com/repositories/12345?per_page=100&page=2>; rel="next")
json [
{ tag_name: 'v1.2.0',
name: 'will_paginate 1.2.0',
draft: false,
prerelease: false,
},
]
}
get('/repositories/12345') {
assert :per_page => "100"
if params[:page] == "2"
response.headers["Link"] = %(<https://api.github.com/repositories/12345?per_page=100&page=3>; rel="next")
json [
{ tag_name: 'v1.2.0-pre',
name: 'will_paginate 1.2.0-pre',
draft: false,
prerelease: true,
},
{ tag_name: 'v1.0.2',
name: 'will_paginate 1.0.2',
draft: false,
prerelease: false,
},
]
elsif params[:page] == "3"
json [
{ tag_name: 'v1.0.0',
name: 'will_paginate 1.0.0',
draft: false,
prerelease: true,
},
]
else
status 400
end
}
"""
When I successfully run `hub release`
Then the output should contain exactly:
"""
v1.2.0
v1.2.0-pre
v1.0.2
v1.0.0\n
"""
Scenario: Repository not found when listing releases
Given the GitHub API server:
"""
......
......@@ -107,6 +107,10 @@ setup_tmp_home = lambda { |shell|
}
$tmux = nil
$installed_shells = Hash.new { |cache, shell|
`which #{shell} 2>/dev/null`
cache[shell] = $?.success?
}
Before('@completion') do
unless $tmux
......@@ -126,7 +130,12 @@ World Module.new {
attr_reader :shell
def set_shell(shell)
@shell = shell
if $installed_shells[shell]
@shell = shell
true
else
false
end
end
define_method(:tmux_pane) do
......@@ -183,7 +192,7 @@ World Module.new {
end
def tmux_output_lines
tmux_pane_contents.split("\n").reject do |line|
tmux_pane_contents.split("\n").drop_while { |l| not l.start_with?('$') }.reject do |line|
line.start_with?('$')
end
end
......@@ -221,7 +230,7 @@ World Module.new {
}
Given(/^my shell is (\w+)$/) do |shell|
set_shell(shell)
set_shell(shell) || pending
setup_tmp_home.call(shell)
end
......
......@@ -274,19 +274,30 @@ type ReleaseAsset struct {
ApiUrl string `json:"url"`
}
func (client *Client) FetchReleases(project *Project) (response []Release, err error) {
func (client *Client) FetchReleases(project *Project) (releases []Release, err error) {
api, err := client.simpleApi()
if err != nil {
return
}
res, err := api.Get(fmt.Sprintf("repos/%s/%s/releases", project.Owner, project.Name))
if err = checkStatus(200, "fetching releases", res, err); err != nil {
return
}
path := fmt.Sprintf("repos/%s/%s/releases?per_page=100", project.Owner, project.Name)
releases = []Release{}
var res *simpleResponse
response = []Release{}
err = res.Unmarshal(&response)
for path != "" {
res, err = api.Get(path)
if err = checkStatus(200, "fetching releases", res, err); err != nil {
return
}
path = res.Link("next")
releasesPage := []Release{}
if err = res.Unmarshal(&releasesPage); err != nil {
return
}
releases = append(releases, releasesPage...)
}
return
}
......
......@@ -123,8 +123,8 @@ func (e *Editor) readContent() (content []byte, err error) {
func openTextEditor(program, file string) error {
editCmd := cmd.New(program)
r := regexp.MustCompile("[mg]?vi[m]$")
if r.MatchString(program) {
r := regexp.MustCompile(`\b(?:[gm]?vim|vi)(?:\.exe)?$`)
if r.MatchString(editCmd.Name) {
editCmd.WithArg("--cmd")
editCmd.WithArg("set ft=gitcommit tw=0 wrap lbr")
}
......
......@@ -276,7 +276,7 @@ func (c *simpleClient) PatchJSON(path string, payload interface{}) (*simpleRespo
func (c *simpleClient) PostReview(path string, payload interface{}) (*simpleResponse, error) {
return c.jsonRequest("POST", path, payload, func(req *http.Request) {
req.Header.Set("Accept", "application/vnd.github.black-cat-preview+json;charset=utf-8")
req.Header.Set("Accept", "application/vnd.github.thor-preview+json;charset=utf-8")
})
}
......
......@@ -5,8 +5,8 @@ import (
)
func IsHttpsProtocol() bool {
httpProcotol, _ := git.Config("hub.protocol")
if httpProcotol == "https" {
httpProtocol, _ := git.Config("hub.protocol")
if httpProtocol == "https" {
return true
}
......
......@@ -8,12 +8,13 @@ goto checkPrivileges
:: This function takes care of these problems by calling Environment.Get/SetEnvironmentVariable
:: via PowerShell, which lacks these issues.
:appendToUserPath
setlocal EnableDelayedExpansion
set "RUNPS=powershell -NoProfile -ExecutionPolicy Bypass -Command" :: Command to start PowerShell.
set "OLDPATHPS=[Environment]::GetEnvironmentVariable('PATH', 'User')" :: PowerShell command to run to get the old $PATH for the current user.
:: Capture the output of %RUNPS% "%OLDPATHPS%" and set it to OLDPATH
for /f "delims=" %%i in ('%RUNPS% "%OLDPATHPS%"') do (
set "OLDPATH=%%i"
set "OLDPATH=!OLDPATH!%%i"
)
set "NEWPATH=%OLDPATH%;%1"
......
......@@ -25,4 +25,14 @@ script/build
script/build test || STATUS="$?"
script/ruby-test || STATUS="$?"
if [ -n "$CI" ]; then
make fmt >/dev/null
if ! git diff -U1 --exit-code; then
STATUS=1
echo
echo "Some go code was not formatted properly." >&2
echo "Run \`make fmt' locally to fix these errors." >&2
fi
fi
exit "$STATUS"
......@@ -118,6 +118,20 @@ this can be affected with the `GITHUB_HOST` environment variable:
$ GITHUB_HOST=my.git.org git clone myproject
### Environment variables
* `HUB_VERBOSE`:
Enable verbose output from hub commands.
* `HUB_CONFIG`:
Set the location of a custom config file (default: `~/.config/hub`).
* `HUB_PROTOCOL`:
Use one of "https|ssh|git" as preferred protocol for git clone/push.
* `GITHUB_TOKEN`:
OAuth token to use for GitHub API requests.
## BUGS
<https://github.com/github/hub/issues>
......
......@@ -20,7 +20,7 @@ type expander struct {
// values is the map of values that should be expanded.
values map[string]string
// colorize is a flag to indiciate whether to use colors.
// colorize is a flag to indicate whether to use colors.
colorize bool
// skipNext is true if the next placeholder is not a placeholder and can be
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册