Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sync gitea app path for git hooks and authorized keys when starting #17335

Merged
merged 20 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion contrib/pr/checkout.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ func runPR() {
dbCfg.NewKey("DB_TYPE", "sqlite3")
dbCfg.NewKey("PATH", ":memory:")

routers.NewServices()
routers.InitGitServices()
setting.Database.LogSQL = true
//x, err = xorm.NewEngine("sqlite3", "file::memory:?cache=shared")

Expand Down
17 changes: 17 additions & 0 deletions modules/appstate/appstate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package appstate

// StateStore is the interface to get/set app state items
type StateStore interface {
Get(item StateItem) error
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
Set(item StateItem) error
Delete(item StateItem) error
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
}

// StateItem provides the name for a state item. the name will be used to generate filenames, etc
type StateItem interface {
Name() string
}
59 changes: 59 additions & 0 deletions modules/appstate/file.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package appstate

import (
"io/fs"
"io/ioutil"
"os"
"path/filepath"

"code.gitea.io/gitea/modules/json"
)

// FileStore can be used to store app state items in local filesystem
type FileStore struct {
path string
}

func (f *FileStore) genFilePath(item StateItem) string {
return filepath.Join(f.path, item.Name())
}

// Get reads the state item
func (f *FileStore) Get(item StateItem) error {
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
b, e := ioutil.ReadFile(f.genFilePath(item))
if os.IsNotExist(e) {
return nil
}
if e != nil {
return e
}
e = json.Unmarshal(b, item)
return e
}

// Set saves the state item
func (f *FileStore) Set(item StateItem) error {
b, e := json.Marshal(item)
if e != nil {
return e
}
return ioutil.WriteFile(f.genFilePath(item), b, fs.FileMode(0644))
}

// Delete removes the state item
func (f *FileStore) Delete(item StateItem) error {
return os.Remove(f.genFilePath(item))
}

// NewFileStore returns a new file store
func NewFileStore(path string) (*FileStore, error) {
_ = os.Mkdir(path, fs.FileMode(0755))
if _, err := os.Stat(path); err != nil {
return nil, err
}
return &FileStore{path: path}, nil
}
15 changes: 15 additions & 0 deletions modules/appstate/item_runtime.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package appstate

// RuntimeState contains app state for runtime, and we can save remote version for update checker here in future
type RuntimeState struct {
LastAppPath string `json:"last_app_path"`
}

// Name returns the item name
func (a RuntimeState) Name() string {
return "runtime-state"
}
58 changes: 42 additions & 16 deletions modules/repository/hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,64 +23,90 @@ import (
func getHookTemplates() (hookNames, hookTpls, giteaHookTpls []string) {
hookNames = []string{"pre-receive", "update", "post-receive"}
hookTpls = []string{
// for pre-receive
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
data=$(cat)
exitcodes=""
hookname=$(basename $0)
GIT_DIR=${GIT_DIR:-$(dirname $0)/..}

for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
test -x "${hook}" && test -f "${hook}" || continue
echo "${data}" | "${hook}"
exitcodes="${exitcodes} $?"
test -x "${hook}" && test -f "${hook}" || continue
echo "${data}" | "${hook}"
exitcodes="${exitcodes} $?"
done

for i in ${exitcodes}; do
[ ${i} -eq 0 ] || exit ${i}
[ ${i} -eq 0 ] || exit ${i}
done
`, setting.ScriptType),

// for update
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
exitcodes=""
hookname=$(basename $0)
GIT_DIR=${GIT_DIR:-$(dirname $0/..)}

for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
test -x "${hook}" && test -f "${hook}" || continue
"${hook}" $1 $2 $3
exitcodes="${exitcodes} $?"
test -x "${hook}" && test -f "${hook}" || continue
"${hook}" $1 $2 $3
exitcodes="${exitcodes} $?"
done

for i in ${exitcodes}; do
[ ${i} -eq 0 ] || exit ${i}
[ ${i} -eq 0 ] || exit ${i}
done
`, setting.ScriptType),

// for post-receive
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
data=$(cat)
exitcodes=""
hookname=$(basename $0)
GIT_DIR=${GIT_DIR:-$(dirname $0)/..}

for hook in ${GIT_DIR}/hooks/${hookname}.d/*; do
test -x "${hook}" && test -f "${hook}" || continue
echo "${data}" | "${hook}"
exitcodes="${exitcodes} $?"
test -x "${hook}" && test -f "${hook}" || continue
echo "${data}" | "${hook}"
exitcodes="${exitcodes} $?"
done

for i in ${exitcodes}; do
[ ${i} -eq 0 ] || exit ${i}
[ ${i} -eq 0 ] || exit ${i}
done
`, setting.ScriptType),
}

giteaHookTpls = []string{
fmt.Sprintf("#!/usr/bin/env %s\n%s hook --config=%s pre-receive\n", setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
fmt.Sprintf("#!/usr/bin/env %s\n%s hook --config=%s update $1 $2 $3\n", setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
fmt.Sprintf("#!/usr/bin/env %s\n%s hook --config=%s post-receive\n", setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
// for pre-receive
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
%s hook --config=%s pre-receive
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),

// for update
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
%s hook --config=%s update $1 $2 $3
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),

// for post-receive
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
%s hook --config=%s post-receive
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)),
}

if git.SupportProcReceive {
hookNames = append(hookNames, "proc-receive")
hookTpls = append(hookTpls,
fmt.Sprintf("#!/usr/bin/env %s\n%s hook --config=%s proc-receive\n", setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)))
fmt.Sprintf(`#!/usr/bin/env %s
# AUTO GENERATED BY GITEA, DO NOT MODIFY
%s hook --config=%s proc-receive
`, setting.ScriptType, util.ShellEscape(setting.AppPath), util.ShellEscape(setting.CustomConf)))
giteaHookTpls = append(giteaHookTpls, "")
}

Expand Down
24 changes: 24 additions & 0 deletions modules/setting/appstate.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2021 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.

package setting

import (
"path/filepath"

"code.gitea.io/gitea/modules/appstate"
"code.gitea.io/gitea/modules/log"
)

// AppState contains the state items for the app
var AppState appstate.StateStore

func newAppState() {
var err error
appStatePath := filepath.Join(AppDataPath, "appstate")
AppState, err = appstate.NewFileStore(appStatePath)
if err != nil {
log.Fatal("failed to init AppState, err = %v", err)
}
}
13 changes: 13 additions & 0 deletions modules/setting/setting.go
Original file line number Diff line number Diff line change
Expand Up @@ -687,6 +687,18 @@ func NewContext() {
StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(StaticRootPath)
StaticCacheTime = sec.Key("STATIC_CACHE_TIME").MustDuration(6 * time.Hour)
AppDataPath = sec.Key("APP_DATA_PATH").MustString(path.Join(AppWorkPath, "data"))
if _, err = os.Stat(AppDataPath); err != nil {
// FIXME: Many calls to MkdirAll are using 0644 (not executable) or `os.ModePerm`(0o777, world-wide writable), which are incorrect.
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
// FIXME: There are too many calls to MkdirAll in old code. It is incorrect.
// For example, if someDir=/mnt/vol1/gitea-home/data, if the mount point /mnt/vol1 is not mounted when Gitea runs,
// then gitea will make new empty directories in /mnt/vol1, all are stored in the root filesystem.
// The correct behavior should be: creating parent directories is end users' duty. We only create sub-directories in existing parent directories.
// Now we can take the first step to do correctly (Mkdir) in other packages, and prepare the AppDataPath here, then make a refactor in future.
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
err = os.MkdirAll(AppDataPath, os.FileMode(0755))
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
log.Fatal("Failed to create the directory for app data path '%s'", AppDataPath)
}
}
EnableGzip = sec.Key("ENABLE_GZIP").MustBool()
EnablePprof = sec.Key("ENABLE_PPROF").MustBool(false)
PprofDataPath = sec.Key("PPROF_DATA_PATH").MustString(path.Join(AppWorkPath, "data/tmp/pprof"))
Expand Down Expand Up @@ -1188,6 +1200,7 @@ func CreateOrAppendToCustomConf(callback func(cfg *ini.File)) {
func NewServices() {
InitDBConfig()
newService()
newAppState()
newOAuth2Client()
NewLogServices(false)
newCacheService()
Expand Down
Loading