2016-11-04 01:16:01 +03:00
// Copyright 2015 The Gogs Authors. All rights reserved.
2019-04-19 15:17:27 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2016-11-04 01:16:01 +03:00
package git
import (
"bytes"
2021-03-04 03:48:19 +03:00
"io"
2016-11-04 01:16:01 +03:00
"strconv"
"strings"
2021-06-26 14:28:55 +03:00
2022-07-30 11:09:04 +03:00
"code.gitea.io/gitea/modules/cache"
2021-06-26 14:28:55 +03:00
"code.gitea.io/gitea/modules/setting"
2016-11-04 01:16:01 +03:00
)
// GetBranchCommitID returns last commit ID string of given branch.
func ( repo * Repository ) GetBranchCommitID ( name string ) ( string , error ) {
2018-01-19 09:18:51 +03:00
return repo . GetRefCommitID ( BranchPrefix + name )
2016-11-04 01:16:01 +03:00
}
// GetTagCommitID returns last commit ID string of given tag.
func ( repo * Repository ) GetTagCommitID ( name string ) ( string , error ) {
2021-04-14 17:22:37 +03:00
return repo . GetRefCommitID ( TagPrefix + name )
2016-11-04 01:16:01 +03:00
}
2019-08-05 23:39:39 +03:00
// GetCommit returns commit object of by ID string.
func ( repo * Repository ) GetCommit ( commitID string ) ( * Commit , error ) {
2023-12-14 00:02:00 +03:00
id , err := repo . ConvertToGitID ( commitID )
2016-11-04 01:16:01 +03:00
if err != nil {
return nil , err
}
return repo . getCommit ( id )
}
// GetBranchCommit returns the last commit of given branch.
func ( repo * Repository ) GetBranchCommit ( name string ) ( * Commit , error ) {
commitID , err := repo . GetBranchCommitID ( name )
if err != nil {
return nil , err
}
return repo . GetCommit ( commitID )
}
2016-12-22 12:30:52 +03:00
// GetTagCommit get the commit of the specific tag via name
2016-11-04 01:16:01 +03:00
func ( repo * Repository ) GetTagCommit ( name string ) ( * Commit , error ) {
commitID , err := repo . GetTagCommitID ( name )
if err != nil {
return nil , err
}
return repo . GetCommit ( commitID )
}
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) getCommitByPathWithID ( id ObjectID , relpath string ) ( * Commit , error ) {
2016-11-04 01:16:01 +03:00
// File name starts with ':' must be escaped.
if relpath [ 0 ] == ':' {
relpath = ` \ ` + relpath
}
2022-10-23 17:44:45 +03:00
stdout , _ , runErr := NewCommand ( repo . Ctx , "log" , "-1" , prettyLogFormat ) . AddDynamicArguments ( id . String ( ) ) . AddDashesAndList ( relpath ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2022-04-01 05:55:30 +03:00
if runErr != nil {
return nil , runErr
2016-11-04 01:16:01 +03:00
}
2023-12-19 10:20:47 +03:00
id , err := NewIDFromString ( stdout )
2016-11-04 01:16:01 +03:00
if err != nil {
return nil , err
}
return repo . getCommit ( id )
}
// GetCommitByPath returns the last commit of relative path.
func ( repo * Repository ) GetCommitByPath ( relpath string ) ( * Commit , error ) {
2022-10-23 17:44:45 +03:00
stdout , _ , runErr := NewCommand ( repo . Ctx , "log" , "-1" , prettyLogFormat ) . AddDashesAndList ( relpath ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2022-04-01 05:55:30 +03:00
if runErr != nil {
return nil , runErr
2016-11-04 01:16:01 +03:00
}
commits , err := repo . parsePrettyFormatLogToList ( stdout )
if err != nil {
return nil , err
}
2023-04-19 20:50:10 +03:00
if len ( commits ) == 0 {
return nil , ErrNotExist { ID : relpath }
}
2021-08-09 21:08:51 +03:00
return commits [ 0 ] , nil
2016-11-04 01:16:01 +03:00
}
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) commitsByRange ( id ObjectID , page , pageSize int , not string ) ( [ ] * Commit , error ) {
2023-04-29 15:34:14 +03:00
cmd := NewCommand ( repo . Ctx , "log" ) .
AddOptionFormat ( "--skip=%d" , ( page - 1 ) * pageSize ) .
AddOptionFormat ( "--max-count=%d" , pageSize ) .
AddArguments ( prettyLogFormat ) .
AddDynamicArguments ( id . String ( ) )
if not != "" {
cmd . AddOptionValues ( "--not" , not )
}
stdout , _ , err := cmd . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2016-11-04 01:16:01 +03:00
if err != nil {
return nil , err
}
2023-04-29 15:34:14 +03:00
2016-11-04 01:16:01 +03:00
return repo . parsePrettyFormatLogToList ( stdout )
}
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) searchCommits ( id ObjectID , opts SearchCommitsOptions ) ( [ ] * Commit , error ) {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
// add common arguments to git command
addCommonSearchArgs := func ( c * Command ) {
// ignore case
c . AddArguments ( "-i" )
// add authors if present in search query
2023-10-06 09:49:37 +03:00
for _ , v := range opts . Authors {
c . AddOptionFormat ( "--author=%s" , v )
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
}
2020-06-12 00:44:39 +03:00
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
// add committers if present in search query
2023-10-06 09:49:37 +03:00
for _ , v := range opts . Committers {
c . AddOptionFormat ( "--committer=%s" , v )
2019-04-12 05:28:44 +03:00
}
2020-06-12 00:44:39 +03:00
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
// add time constraints if present in search query
if len ( opts . After ) > 0 {
c . AddOptionFormat ( "--after=%s" , opts . After )
}
if len ( opts . Before ) > 0 {
c . AddOptionFormat ( "--before=%s" , opts . Before )
2019-04-12 05:28:44 +03:00
}
}
2020-06-12 00:44:39 +03:00
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
// create new git log command with limit of 100 commits
cmd := NewCommand ( repo . Ctx , "log" , "-100" , prettyLogFormat ) . AddDynamicArguments ( id . String ( ) )
2020-06-12 00:44:39 +03:00
// pretend that all refs along with HEAD were listed on command line as <commis>
// https://git-scm.com/docs/git-log#Documentation/git-log.txt---all
// note this is done only for command created above
2019-04-12 05:28:44 +03:00
if opts . All {
2020-06-12 00:44:39 +03:00
cmd . AddArguments ( "--all" )
2019-09-03 02:38:04 +03:00
}
2020-06-12 00:44:39 +03:00
2024-01-10 14:28:20 +03:00
// interpret search string keywords as string instead of regex
2024-01-11 06:04:45 +03:00
cmd . AddArguments ( "--fixed-strings" )
2024-01-10 14:28:20 +03:00
2020-06-12 00:44:39 +03:00
// add remaining keywords from search string
// note this is done only for command created above
2023-10-06 09:49:37 +03:00
for _ , v := range opts . Keywords {
cmd . AddOptionFormat ( "--grep=%s" , v )
2017-02-05 17:43:28 +03:00
}
2020-06-12 00:44:39 +03:00
// search for commits matching given constraints and keywords in commit msg
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
addCommonSearchArgs ( cmd )
2022-04-01 05:55:30 +03:00
stdout , _ , err := cmd . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2016-11-04 01:16:01 +03:00
if err != nil {
return nil , err
}
2019-09-03 02:38:04 +03:00
if len ( stdout ) != 0 {
stdout = append ( stdout , '\n' )
}
2020-06-12 00:44:39 +03:00
2021-07-08 14:38:13 +03:00
// if there are any keywords (ie not committer:, author:, time:)
2020-06-12 00:44:39 +03:00
// then let's iterate over them
2023-10-06 09:49:37 +03:00
for _ , v := range opts . Keywords {
// ignore anything not matching a valid sha pattern
2023-12-14 00:02:00 +03:00
if id . Type ( ) . IsValid ( v ) {
2023-10-06 09:49:37 +03:00
// create new git log command with 1 commit limit
hashCmd := NewCommand ( repo . Ctx , "log" , "-1" , prettyLogFormat )
// add previous arguments except for --grep and --all
addCommonSearchArgs ( hashCmd )
// add keyword as <commit>
hashCmd . AddDynamicArguments ( v )
// search with given constraints for commit matching sha hash of v
hashMatching , _ , err := hashCmd . RunStdBytes ( & RunOpts { Dir : repo . Path } )
if err != nil || bytes . Contains ( stdout , hashMatching ) {
continue
2019-09-03 02:38:04 +03:00
}
2023-10-06 09:49:37 +03:00
stdout = append ( stdout , hashMatching ... )
stdout = append ( stdout , '\n' )
2019-09-03 02:38:04 +03:00
}
}
return repo . parsePrettyFormatLogToList ( bytes . TrimSuffix ( stdout , [ ] byte { '\n' } ) )
2016-11-04 01:16:01 +03:00
}
2019-04-17 19:06:35 +03:00
// FileChangedBetweenCommits Returns true if the file changed between commit IDs id1 and id2
2019-08-05 23:39:39 +03:00
// You must ensure that id1 and id2 are valid commit ids.
2019-04-17 19:06:35 +03:00
func ( repo * Repository ) FileChangedBetweenCommits ( filename , id1 , id2 string ) ( bool , error ) {
2022-10-23 17:44:45 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "diff" , "--name-only" , "-z" ) . AddDynamicArguments ( id1 , id2 ) . AddDashesAndList ( filename ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2019-04-17 19:06:35 +03:00
if err != nil {
return false , err
}
return len ( strings . TrimSpace ( string ( stdout ) ) ) > 0 , nil
}
2021-07-08 14:38:13 +03:00
// FileCommitsCount return the number of files at a revision
2016-11-04 01:16:01 +03:00
func ( repo * Repository ) FileCommitsCount ( revision , file string ) ( int64 , error ) {
2023-05-08 10:10:53 +03:00
return CommitsCount ( repo . Ctx ,
CommitsCountOptions {
RepoPath : repo . Path ,
Revision : [ ] string { revision } ,
RelPath : [ ] string { file } ,
} )
}
type CommitsByFileAndRangeOptions struct {
Revision string
File string
Not string
Page int
2016-11-04 01:16:01 +03:00
}
2021-07-08 14:38:13 +03:00
// CommitsByFileAndRange return the commits according revision file and the page
2023-05-08 10:10:53 +03:00
func ( repo * Repository ) CommitsByFileAndRange ( opts CommitsByFileAndRangeOptions ) ( [ ] * Commit , error ) {
skip := ( opts . Page - 1 ) * setting . Git . CommitsRangeSize
2021-03-04 03:48:19 +03:00
stdoutReader , stdoutWriter := io . Pipe ( )
defer func ( ) {
_ = stdoutReader . Close ( )
_ = stdoutWriter . Close ( )
} ( )
go func ( ) {
stderr := strings . Builder { }
2022-10-23 17:44:45 +03:00
gitCmd := NewCommand ( repo . Ctx , "rev-list" ) .
2023-05-08 10:10:53 +03:00
AddOptionFormat ( "--max-count=%d" , setting . Git . CommitsRangeSize * opts . Page ) .
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
AddOptionFormat ( "--skip=%d" , skip )
2023-05-08 10:10:53 +03:00
gitCmd . AddDynamicArguments ( opts . Revision )
if opts . Not != "" {
gitCmd . AddOptionValues ( "--not" , opts . Not )
}
gitCmd . AddDashesAndList ( opts . File )
2022-10-15 13:49:26 +03:00
err := gitCmd . Run ( & RunOpts {
Dir : repo . Path ,
Stdout : stdoutWriter ,
Stderr : & stderr ,
} )
2021-03-04 03:48:19 +03:00
if err != nil {
_ = stdoutWriter . CloseWithError ( ConcatenateError ( err , ( & stderr ) . String ( ) ) )
} else {
_ = stdoutWriter . Close ( )
}
} ( )
2023-12-14 00:02:00 +03:00
len := repo . objectFormat . FullLength ( )
2022-08-15 04:22:13 +03:00
commits := [ ] * Commit { }
2023-12-14 00:02:00 +03:00
shaline := make ( [ ] byte , len + 1 )
2022-08-15 04:22:13 +03:00
for {
2023-12-14 00:02:00 +03:00
n , err := io . ReadFull ( stdoutReader , shaline )
if err != nil || n < len {
2021-03-04 03:48:19 +03:00
if err == io . EOF {
2022-08-15 04:22:13 +03:00
err = nil
2021-03-04 03:48:19 +03:00
}
2022-08-15 04:22:13 +03:00
return commits , err
}
2023-12-19 10:20:47 +03:00
objectID , err := NewIDFromString ( string ( shaline [ 0 : len ] ) )
2022-08-15 04:22:13 +03:00
if err != nil {
2021-03-04 03:48:19 +03:00
return nil , err
}
2023-12-14 00:02:00 +03:00
commit , err := repo . getCommit ( objectID )
2022-08-15 04:22:13 +03:00
if err != nil {
return nil , err
}
commits = append ( commits , commit )
2021-03-04 03:48:19 +03:00
}
2019-07-11 17:45:10 +03:00
}
2016-12-22 12:30:52 +03:00
// FilesCountBetween return the number of files changed between two commits
2016-11-04 01:16:01 +03:00
func ( repo * Repository ) FilesCountBetween ( startCommitID , endCommitID string ) ( int , error ) {
2022-10-23 17:44:45 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "diff" , "--name-only" ) . AddDynamicArguments ( startCommitID + "..." + endCommitID ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
if err != nil && strings . Contains ( err . Error ( ) , "no merge base" ) {
// git >= 2.28 now returns an error if startCommitID and endCommitID have become unrelated.
// previously it would return the results of git diff --name-only startCommitID endCommitID so let's try that...
2022-10-23 17:44:45 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "diff" , "--name-only" ) . AddDynamicArguments ( startCommitID , endCommitID ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
}
2016-11-04 01:16:01 +03:00
if err != nil {
return 0 , err
}
return len ( strings . Split ( stdout , "\n" ) ) - 1 , nil
}
2021-06-30 20:49:06 +03:00
// CommitsBetween returns a list that contains commits between [before, last).
// If before is detached (removed by reset + push) it is not included.
2021-12-20 07:41:31 +03:00
func ( repo * Repository ) CommitsBetween ( last , before * Commit ) ( [ ] * Commit , error ) {
2019-12-31 02:34:11 +03:00
var stdout [ ] byte
var err error
if before == nil {
2022-10-23 17:44:45 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2019-12-31 02:34:11 +03:00
} else {
2022-10-23 17:44:45 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( before . ID . String ( ) + ".." + last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
if err != nil && strings . Contains ( err . Error ( ) , "no merge base" ) {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
2022-10-23 17:44:45 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( before . ID . String ( ) , last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
}
2019-12-31 02:34:11 +03:00
}
if err != nil {
return nil , err
}
return repo . parsePrettyFormatLogToList ( bytes . TrimSpace ( stdout ) )
}
2021-06-30 20:49:06 +03:00
// CommitsBetweenLimit returns a list that contains at most limit commits skipping the first skip commits between [before, last)
2021-12-20 07:41:31 +03:00
func ( repo * Repository ) CommitsBetweenLimit ( last , before * Commit , limit , skip int ) ( [ ] * Commit , error ) {
2019-12-31 02:34:11 +03:00
var stdout [ ] byte
var err error
if before == nil {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) .
AddOptionValues ( "--max-count" , strconv . Itoa ( limit ) ) .
AddOptionValues ( "--skip" , strconv . Itoa ( skip ) ) .
2022-10-23 17:44:45 +03:00
AddDynamicArguments ( last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2019-12-31 02:34:11 +03:00
} else {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) .
AddOptionValues ( "--max-count" , strconv . Itoa ( limit ) ) .
AddOptionValues ( "--skip" , strconv . Itoa ( skip ) ) .
2022-10-23 17:44:45 +03:00
AddDynamicArguments ( before . ID . String ( ) + ".." + last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
if err != nil && strings . Contains ( err . Error ( ) , "no merge base" ) {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list --max-count n before last so let's try that...
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) .
AddOptionValues ( "--max-count" , strconv . Itoa ( limit ) ) .
AddOptionValues ( "--skip" , strconv . Itoa ( skip ) ) .
2022-10-23 17:44:45 +03:00
AddDynamicArguments ( before . ID . String ( ) , last . ID . String ( ) ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
2020-07-29 20:53:04 +03:00
}
2019-12-31 02:34:11 +03:00
}
2017-10-23 16:36:14 +03:00
if err != nil {
return nil , err
2016-11-04 01:16:01 +03:00
}
2017-10-23 16:36:14 +03:00
return repo . parsePrettyFormatLogToList ( bytes . TrimSpace ( stdout ) )
2016-11-04 01:16:01 +03:00
}
2023-03-09 21:14:22 +03:00
// CommitsBetweenNotBase returns a list that contains commits between [before, last), excluding commits in baseBranch.
// If before is detached (removed by reset + push) it is not included.
func ( repo * Repository ) CommitsBetweenNotBase ( last , before * Commit , baseBranch string ) ( [ ] * Commit , error ) {
var stdout [ ] byte
var err error
if before == nil {
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( last . ID . String ( ) ) . AddOptionValues ( "--not" , baseBranch ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
} else {
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( before . ID . String ( ) + ".." + last . ID . String ( ) ) . AddOptionValues ( "--not" , baseBranch ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
if err != nil && strings . Contains ( err . Error ( ) , "no merge base" ) {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
stdout , _ , err = NewCommand ( repo . Ctx , "rev-list" ) . AddDynamicArguments ( before . ID . String ( ) , last . ID . String ( ) ) . AddOptionValues ( "--not" , baseBranch ) . RunStdBytes ( & RunOpts { Dir : repo . Path } )
}
}
if err != nil {
return nil , err
}
return repo . parsePrettyFormatLogToList ( bytes . TrimSpace ( stdout ) )
}
2016-12-22 12:30:52 +03:00
// CommitsBetweenIDs return commits between twoe commits
2021-08-09 21:08:51 +03:00
func ( repo * Repository ) CommitsBetweenIDs ( last , before string ) ( [ ] * Commit , error ) {
2016-11-04 01:16:01 +03:00
lastCommit , err := repo . GetCommit ( last )
if err != nil {
return nil , err
}
2019-12-31 02:34:11 +03:00
if before == "" {
return repo . CommitsBetween ( lastCommit , nil )
}
2016-11-04 01:16:01 +03:00
beforeCommit , err := repo . GetCommit ( before )
if err != nil {
return nil , err
}
return repo . CommitsBetween ( lastCommit , beforeCommit )
}
2016-12-22 12:30:52 +03:00
// CommitsCountBetween return numbers of commits between two commits
2016-11-04 01:16:01 +03:00
func ( repo * Repository ) CommitsCountBetween ( start , end string ) ( int64 , error ) {
2023-05-08 10:10:53 +03:00
count , err := CommitsCount ( repo . Ctx , CommitsCountOptions {
RepoPath : repo . Path ,
Revision : [ ] string { start + ".." + end } ,
} )
2020-07-29 20:53:04 +03:00
if err != nil && strings . Contains ( err . Error ( ) , "no merge base" ) {
// future versions of git >= 2.28 are likely to return an error if before and last have become unrelated.
// previously it would return the results of git rev-list before last so let's try that...
2023-05-08 10:10:53 +03:00
return CommitsCount ( repo . Ctx , CommitsCountOptions {
RepoPath : repo . Path ,
Revision : [ ] string { start , end } ,
} )
2020-07-29 20:53:04 +03:00
}
return count , err
2016-11-04 01:16:01 +03:00
}
2016-12-22 12:30:52 +03:00
// commitsBefore the limit is depth, not total number of returned commits.
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) commitsBefore ( id ObjectID , limit int ) ( [ ] * Commit , error ) {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
cmd := NewCommand ( repo . Ctx , "log" , prettyLogFormat )
2017-12-11 05:23:34 +03:00
if limit > 0 {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
cmd . AddOptionFormat ( "-%d" , limit )
2016-11-04 01:16:01 +03:00
}
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
cmd . AddDynamicArguments ( id . String ( ) )
2016-11-04 01:16:01 +03:00
2022-04-01 05:55:30 +03:00
stdout , _ , runErr := cmd . RunStdBytes ( & RunOpts { Dir : repo . Path } )
if runErr != nil {
return nil , runErr
2016-11-04 01:16:01 +03:00
}
2017-12-11 05:23:34 +03:00
formattedLog , err := repo . parsePrettyFormatLogToList ( bytes . TrimSpace ( stdout ) )
if err != nil {
return nil , err
2016-11-04 01:16:01 +03:00
}
2021-08-09 21:08:51 +03:00
commits := make ( [ ] * Commit , 0 , len ( formattedLog ) )
for _ , commit := range formattedLog {
2017-12-11 05:23:34 +03:00
branches , err := repo . getBranches ( commit , 2 )
2016-11-04 01:16:01 +03:00
if err != nil {
2017-12-11 05:23:34 +03:00
return nil , err
2016-11-04 01:16:01 +03:00
}
2017-12-11 05:23:34 +03:00
if len ( branches ) > 1 {
break
2016-11-04 01:16:01 +03:00
}
2017-12-11 05:23:34 +03:00
2021-08-09 21:08:51 +03:00
commits = append ( commits , commit )
2016-11-04 01:16:01 +03:00
}
2017-12-11 05:23:34 +03:00
return commits , nil
2016-11-04 01:16:01 +03:00
}
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) getCommitsBefore ( id ObjectID ) ( [ ] * Commit , error ) {
2017-12-11 05:23:34 +03:00
return repo . commitsBefore ( id , 0 )
2016-11-04 01:16:01 +03:00
}
2023-12-14 00:02:00 +03:00
func ( repo * Repository ) getCommitsBeforeLimit ( id ObjectID , num int ) ( [ ] * Commit , error ) {
2017-12-11 05:23:34 +03:00
return repo . commitsBefore ( id , num )
}
func ( repo * Repository ) getBranches ( commit * Commit , limit int ) ( [ ] string , error ) {
2020-10-21 18:42:08 +03:00
if CheckGitVersionAtLeast ( "2.7.0" ) == nil {
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "for-each-ref" , "--format=%(refname:strip=2)" ) .
AddOptionFormat ( "--count=%d" , limit ) .
AddOptionValues ( "--contains" , commit . ID . String ( ) , BranchPrefix ) .
2022-10-23 17:44:45 +03:00
RunStdString ( & RunOpts { Dir : repo . Path } )
2018-05-27 21:47:34 +03:00
if err != nil {
return nil , err
}
branches := strings . Fields ( stdout )
return branches , nil
}
Refactor git command package to improve security and maintainability (#22678)
This PR follows #21535 (and replace #22592)
## Review without space diff
https://github.com/go-gitea/gitea/pull/22678/files?diff=split&w=1
## Purpose of this PR
1. Make git module command completely safe (risky user inputs won't be
passed as argument option anymore)
2. Avoid low-level mistakes like
https://github.com/go-gitea/gitea/pull/22098#discussion_r1045234918
3. Remove deprecated and dirty `CmdArgCheck` function, hide the `CmdArg`
type
4. Simplify code when using git command
## The main idea of this PR
* Move the `git.CmdArg` to the `internal` package, then no other package
except `git` could use it. Then developers could never do
`AddArguments(git.CmdArg(userInput))` any more.
* Introduce `git.ToTrustedCmdArgs`, it's for user-provided and already
trusted arguments. It's only used in a few cases, for example: use git
arguments from config file, help unit test with some arguments.
* Introduce `AddOptionValues` and `AddOptionFormat`, they make code more
clear and simple:
* Before: `AddArguments("-m").AddDynamicArguments(message)`
* After: `AddOptionValues("-m", message)`
* -
* Before: `AddArguments(git.CmdArg(fmt.Sprintf("--author='%s <%s>'",
sig.Name, sig.Email)))`
* After: `AddOptionFormat("--author='%s <%s>'", sig.Name, sig.Email)`
## FAQ
### Why these changes were not done in #21535 ?
#21535 is mainly a search&replace, it did its best to not change too
much logic.
Making the framework better needs a lot of changes, so this separate PR
is needed as the second step.
### The naming of `AddOptionXxx`
According to git's manual, the `--xxx` part is called `option`.
### How can it guarantee that `internal.CmdArg` won't be not misused?
Go's specification guarantees that. Trying to access other package's
internal package causes compilation error.
And, `golangci-lint` also denies the git/internal package. Only the
`git/command.go` can use it carefully.
### There is still a `ToTrustedCmdArgs`, will it still allow developers
to make mistakes and pass untrusted arguments?
Generally speaking, no. Because when using `ToTrustedCmdArgs`, the code
will be very complex (see the changes for examples). Then developers and
reviewers can know that something might be unreasonable.
### Why there was a `CmdArgCheck` and why it's removed?
At the moment of #21535, to reduce unnecessary changes, `CmdArgCheck`
was introduced as a hacky patch. Now, almost all code could be written
as `cmd := NewCommand(); cmd.AddXxx(...)`, then there is no need for
`CmdArgCheck` anymore.
### Why many codes for `signArg == ""` is deleted?
Because in the old code, `signArg` could never be empty string, it's
either `-S[key-id]` or `--no-gpg-sign`. So the `signArg == ""` is just
dead code.
---------
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
2023-02-04 05:30:43 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "branch" ) . AddOptionValues ( "--contains" , commit . ID . String ( ) ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2017-12-11 05:23:34 +03:00
if err != nil {
return nil , err
}
refs := strings . Split ( stdout , "\n" )
2018-05-27 21:47:34 +03:00
var max int
if len ( refs ) > limit {
max = limit
} else {
max = len ( refs ) - 1
}
branches := make ( [ ] string , max )
for i , ref := range refs [ : max ] {
parts := strings . Fields ( ref )
branches [ i ] = parts [ len ( parts ) - 1 ]
2017-12-11 05:23:34 +03:00
}
return branches , nil
2016-11-04 01:16:01 +03:00
}
2020-05-20 15:47:24 +03:00
// GetCommitsFromIDs get commits from commit IDs
2021-08-09 21:08:51 +03:00
func ( repo * Repository ) GetCommitsFromIDs ( commitIDs [ ] string ) [ ] * Commit {
commits := make ( [ ] * Commit , 0 , len ( commitIDs ) )
2020-05-20 15:47:24 +03:00
for _ , commitID := range commitIDs {
commit , err := repo . GetCommit ( commitID )
if err == nil && commit != nil {
2021-08-09 21:08:51 +03:00
commits = append ( commits , commit )
2020-05-20 15:47:24 +03:00
}
}
return commits
}
2021-03-04 06:41:23 +03:00
// IsCommitInBranch check if the commit is on the branch
func ( repo * Repository ) IsCommitInBranch ( commitID , branch string ) ( r bool , err error ) {
2022-10-23 17:44:45 +03:00
stdout , _ , err := NewCommand ( repo . Ctx , "branch" , "--contains" ) . AddDynamicArguments ( commitID , branch ) . RunStdString ( & RunOpts { Dir : repo . Path } )
2021-03-04 06:41:23 +03:00
if err != nil {
return false , err
}
return len ( stdout ) > 0 , err
}
2022-07-30 11:09:04 +03:00
func ( repo * Repository ) AddLastCommitCache ( cacheKey , fullName , sha string ) error {
if repo . LastCommitCache == nil {
commitsCount , err := cache . GetInt64 ( cacheKey , func ( ) ( int64 , error ) {
commit , err := repo . GetCommit ( sha )
if err != nil {
return 0 , err
}
return commit . CommitsCount ( )
} )
if err != nil {
return err
}
repo . LastCommitCache = NewLastCommitCache ( commitsCount , fullName , repo , cache . GetCache ( ) )
}
return nil
}