2019-02-04 00:56:53 +01:00
// Copyright 2019 The Gitea Authors. All rights reserved.
2022-11-27 19:20:29 +01:00
// SPDX-License-Identifier: MIT
2019-02-04 00:56:53 +01:00
2022-09-02 21:18:23 +02:00
package integration
2019-02-04 00:56:53 +01:00
import (
"context"
"fmt"
"net"
"net/http"
"net/url"
"os"
2019-10-12 02:13:27 +02:00
"path"
2019-02-04 00:56:53 +01:00
"path/filepath"
2024-11-14 02:13:22 +01:00
"regexp"
2021-11-06 07:23:32 +01:00
"strconv"
2019-02-04 00:56:53 +01:00
"testing"
"time"
2019-03-27 10:33:00 +01:00
"code.gitea.io/gitea/modules/git"
2019-02-04 00:56:53 +01:00
"code.gitea.io/gitea/modules/setting"
2020-08-11 22:05:34 +02:00
"code.gitea.io/gitea/modules/util"
2022-09-02 21:18:23 +02:00
"code.gitea.io/gitea/tests"
2019-08-23 18:40:30 +02:00
2019-02-04 00:56:53 +01:00
"github.com/stretchr/testify/assert"
2024-07-30 21:41:10 +02:00
"github.com/stretchr/testify/require"
2019-02-04 00:56:53 +01:00
)
func withKeyFile ( t * testing . T , keyname string , callback func ( string ) ) {
2022-09-04 17:14:53 +02:00
tmpDir := t . TempDir ( )
2019-08-14 13:19:13 +02:00
2022-09-04 17:14:53 +02:00
err := os . Chmod ( tmpDir , 0 o700 )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-08-14 13:19:13 +02:00
keyFile := filepath . Join ( tmpDir , keyname )
2024-11-14 11:18:48 +01:00
pubkey , privkey , err := util . GenerateSSHKeypair ( )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2024-11-14 11:18:48 +01:00
require . NoError ( t , os . WriteFile ( keyFile , privkey , 0 o600 ) )
require . NoError ( t , os . WriteFile ( keyFile + ".pub" , pubkey , 0 o600 ) )
2019-02-04 00:56:53 +01:00
2021-09-22 07:38:34 +02:00
err = os . WriteFile ( path . Join ( tmpDir , "ssh" ) , [ ] byte ( "#!/bin/bash\n" +
2022-01-20 18:46:10 +01:00
"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \"" + keyFile + "\" \"$@\"" ) , 0 o700 )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-10-12 02:13:27 +02:00
2022-01-20 18:46:10 +01:00
// Setup ssh wrapper
2024-07-17 23:07:41 +02:00
t . Setenv ( "GIT_SSH" , path . Join ( tmpDir , "ssh" ) )
t . Setenv ( "GIT_SSH_COMMAND" ,
2019-08-17 00:28:55 +02:00
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o IdentitiesOnly=yes -i \"" + keyFile + "\"" )
2024-07-17 23:07:41 +02:00
t . Setenv ( "GIT_SSH_VARIANT" , "ssh" )
2019-02-04 00:56:53 +01:00
callback ( keyFile )
}
func createSSHUrl ( gitPath string , u * url . URL ) * url . URL {
u2 := * u
u2 . Scheme = "ssh"
u2 . User = url . User ( "git" )
2021-11-06 07:23:32 +01:00
u2 . Host = net . JoinHostPort ( setting . SSH . ListenHost , strconv . Itoa ( setting . SSH . ListenPort ) )
2019-02-04 00:56:53 +01:00
u2 . Path = gitPath
return & u2
}
2024-11-14 02:13:22 +01:00
var rootPathRe = regexp . MustCompile ( "\\[repository\\]\nROOT\\s=\\s.*" )
2023-08-12 18:30:16 +02:00
func onGiteaRun [ T testing . TB ] ( t T , callback func ( T , * url . URL ) ) {
defer tests . PrepareTestEnv ( t , 1 ) ( )
2019-02-04 00:56:53 +01:00
s := http . Server {
2023-08-12 18:30:16 +02:00
Handler : testWebRoutes ,
2019-02-04 00:56:53 +01:00
}
u , err := url . Parse ( setting . AppURL )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-02-04 00:56:53 +01:00
listener , err := net . Listen ( "tcp" , u . Host )
2019-12-15 17:21:16 +01:00
i := 0
for err != nil && i <= 10 {
time . Sleep ( 100 * time . Millisecond )
listener , err = net . Listen ( "tcp" , u . Host )
i ++
}
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-11-26 16:35:41 +01:00
u . Host = listener . Addr ( ) . String ( )
2019-02-04 00:56:53 +01:00
2024-11-14 02:13:22 +01:00
// Override repository root in config.
conf , err := os . ReadFile ( setting . CustomConf )
require . NoError ( t , err )
require . NoError ( t , os . WriteFile ( setting . CustomConf , rootPathRe . ReplaceAll ( conf , [ ] byte ( "[repository]\nROOT = " + setting . RepoRootPath ) ) , os . ModePerm ) )
2019-02-04 00:56:53 +01:00
defer func ( ) {
2024-11-14 02:13:22 +01:00
require . NoError ( t , os . WriteFile ( setting . CustomConf , conf , os . ModePerm ) )
2019-02-04 00:56:53 +01:00
ctx , cancel := context . WithTimeout ( context . Background ( ) , 2 * time . Minute )
s . Shutdown ( ctx )
cancel ( )
} ( )
go s . Serve ( listener )
2022-01-20 18:46:10 +01:00
// Started by config go ssh.Listen(setting.SSH.ListenHost, setting.SSH.ListenPort, setting.SSH.ServerCiphers, setting.SSH.ServerKeyExchanges, setting.SSH.ServerMACs)
2019-02-04 00:56:53 +01:00
callback ( t , u )
}
func doGitClone ( dstLocalPath string , u * url . URL ) func ( * testing . T ) {
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2024-07-30 21:41:10 +02:00
require . NoError ( t , git . CloneWithArgs ( context . Background ( ) , git . AllowLFSFiltersArgs ( ) , u . String ( ) , dstLocalPath , git . CloneRepoOptions { } ) )
2020-12-25 10:59:32 +01:00
exist , err := util . IsExist ( filepath . Join ( dstLocalPath , "README.md" ) )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2020-12-25 10:59:32 +01:00
assert . True ( t , exist )
2019-02-04 00:56:53 +01:00
}
}
2022-01-23 22:19:32 +01:00
func doPartialGitClone ( dstLocalPath string , u * url . URL ) func ( * testing . T ) {
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2024-07-30 21:41:10 +02:00
require . NoError ( t , git . CloneWithArgs ( context . Background ( ) , git . AllowLFSFiltersArgs ( ) , u . String ( ) , dstLocalPath , git . CloneRepoOptions {
2022-01-23 22:19:32 +01:00
Filter : "blob:none" ,
} ) )
exist , err := util . IsExist ( filepath . Join ( dstLocalPath , "README.md" ) )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2022-01-23 22:19:32 +01:00
assert . True ( t , exist )
}
}
2020-04-28 10:32:23 +02:00
func doGitCloneFail ( u * url . URL ) func ( * testing . T ) {
2019-02-04 00:56:53 +01:00
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2022-09-04 17:14:53 +02:00
tmpDir := t . TempDir ( )
2024-07-30 21:41:10 +02:00
require . Error ( t , git . Clone ( git . DefaultContext , u . String ( ) , tmpDir , git . CloneRepoOptions { } ) )
2020-12-25 10:59:32 +01:00
exist , err := util . IsExist ( filepath . Join ( tmpDir , "README.md" ) )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2020-12-25 10:59:32 +01:00
assert . False ( t , exist )
2019-02-04 00:56:53 +01:00
}
}
2024-05-15 15:35:19 +02:00
func doGitInitTestRepository ( dstPath string , objectFormat git . ObjectFormat ) func ( * testing . T ) {
2019-02-04 00:56:53 +01:00
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2019-02-04 00:56:53 +01:00
// Init repository in dstPath
2024-07-30 21:41:10 +02:00
require . NoError ( t , git . InitRepository ( git . DefaultContext , dstPath , false , objectFormat . Name ( ) ) )
2021-12-20 21:55:05 +01:00
// forcibly set default branch to master
2022-04-01 04:55:30 +02:00
_ , _ , err := git . NewCommand ( git . DefaultContext , "symbolic-ref" , "HEAD" , git . BranchPrefix + "master" ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
require . NoError ( t , os . WriteFile ( filepath . Join ( dstPath , "README.md" ) , [ ] byte ( fmt . Sprintf ( "# Testing Repository\n\nOriginally created in: %s" , dstPath ) ) , 0 o644 ) )
require . NoError ( t , git . AddChanges ( dstPath , true ) )
2019-02-04 00:56:53 +01:00
signature := git . Signature {
Email : "test@example.com" ,
Name : "test" ,
When : time . Now ( ) ,
}
2024-07-30 21:41:10 +02:00
require . NoError ( t , git . CommitChanges ( dstPath , git . CommitChangesOptions {
2019-02-04 00:56:53 +01:00
Committer : & signature ,
Author : & signature ,
Message : "Initial Commit" ,
} ) )
}
}
func doGitAddRemote ( dstPath , remoteName string , u * url . URL ) func ( * testing . T ) {
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2022-10-23 16:44:45 +02:00
_ , _ , err := git . NewCommand ( git . DefaultContext , "remote" , "add" ) . AddDynamicArguments ( remoteName , u . String ( ) ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-02-04 00:56:53 +01: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 03:30:43 +01:00
func doGitPushTestRepository ( dstPath string , args ... string ) func ( * testing . T ) {
2019-02-04 00:56:53 +01:00
return func ( t * testing . T ) {
2024-05-15 15:35:19 +02:00
t . Helper ( )
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 03:30:43 +01:00
_ , _ , err := git . NewCommand ( git . DefaultContext , "push" , "-u" ) . AddArguments ( git . ToTrustedCmdArgs ( args ) ... ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-02-04 00:56:53 +01: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 03:30:43 +01:00
func doGitPushTestRepositoryFail ( dstPath string , args ... string ) func ( * testing . T ) {
2019-02-04 00:56:53 +01:00
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
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 03:30:43 +01:00
_ , _ , err := git . NewCommand ( git . DefaultContext , "push" ) . AddArguments ( git . ToTrustedCmdArgs ( args ) ... ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . Error ( t , err )
2019-02-04 00:56:53 +01:00
}
}
2019-05-31 12:12:15 +02:00
2024-05-29 08:43:02 +02:00
func doGitAddSomeCommits ( dstPath , branch string ) func ( * testing . T ) {
return func ( t * testing . T ) {
doGitCheckoutBranch ( dstPath , branch ) ( t )
2024-07-30 21:41:10 +02:00
require . NoError ( t , os . WriteFile ( filepath . Join ( dstPath , fmt . Sprintf ( "file-%s.txt" , branch ) ) , [ ] byte ( fmt . Sprintf ( "file %s" , branch ) ) , 0 o644 ) )
require . NoError ( t , git . AddChanges ( dstPath , true ) )
2024-05-29 08:43:02 +02:00
signature := git . Signature {
Email : "test@test.test" ,
Name : "test" ,
}
2024-07-30 21:41:10 +02:00
require . NoError ( t , git . CommitChanges ( dstPath , git . CommitChangesOptions {
2024-05-29 08:43:02 +02:00
Committer : & signature ,
Author : & signature ,
Message : fmt . Sprintf ( "update %s" , branch ) ,
} ) )
}
}
2019-05-31 12:12:15 +02:00
func doGitCreateBranch ( dstPath , branch string ) func ( * testing . T ) {
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
2022-10-23 16:44:45 +02:00
_ , _ , err := git . NewCommand ( git . DefaultContext , "checkout" , "-b" ) . AddDynamicArguments ( branch ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-05-31 12:12:15 +02: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 03:30:43 +01:00
func doGitCheckoutBranch ( dstPath string , args ... string ) func ( * testing . T ) {
2019-05-31 12:12:15 +02:00
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
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 03:30:43 +01:00
_ , _ , err := git . NewCommandContextNoGlobals ( git . DefaultContext , git . AllowLFSFiltersArgs ( ) ... ) . AddArguments ( "checkout" ) . AddArguments ( git . ToTrustedCmdArgs ( args ) ... ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-05-31 12:12:15 +02: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 03:30:43 +01:00
func doGitPull ( dstPath string , args ... string ) func ( * testing . T ) {
2019-05-31 12:12:15 +02:00
return func ( t * testing . T ) {
2024-06-01 13:57:35 +02:00
t . Helper ( )
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 03:30:43 +01:00
_ , _ , err := git . NewCommandContextNoGlobals ( git . DefaultContext , git . AllowLFSFiltersArgs ( ) ... ) . AddArguments ( "pull" ) . AddArguments ( git . ToTrustedCmdArgs ( args ) ... ) . RunStdString ( & git . RunOpts { Dir : dstPath } )
2024-07-30 21:41:10 +02:00
require . NoError ( t , err )
2019-05-31 12:12:15 +02:00
}
}