## NoDelay=true
##
@@ -52,32 +52,31 @@ After=network.target
# Uncomment the next line if you have repos with lots of files and get a HTTP 500 error because of that
# LimitNOFILE=524288:524288
RestartSec=2s
-Type=notify
+Type=simple
User=git
Group=git
-WorkingDirectory=/var/lib/gitea/
-# If using Unix socket: tells systemd to create the /run/gitea folder, which will contain the gitea.sock file
-# (manually creating /run/gitea doesn't work, because it would not persist across reboots)
-#RuntimeDirectory=gitea
-ExecStart=/usr/local/bin/gitea web --config /etc/gitea/app.ini
+WorkingDirectory=/var/lib/forgejo/
+# If using Unix socket: tells systemd to create the /run/forgejo folder, which will contain the forgejo.sock file
+# (manually creating /run/forgejo doesn't work, because it would not persist across reboots)
+#RuntimeDirectory=forgejo
+ExecStart=/usr/local/bin/forgejo web --config /etc/forgejo/app.ini
Restart=always
-Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/gitea
-WatchdogSec=30s
+Environment=USER=git HOME=/home/git GITEA_WORK_DIR=/var/lib/forgejo
# If you install Git to directory prefix other than default PATH (which happens
# for example if you install other versions of Git side-to-side with
# distribution version), uncomment below line and add that prefix to PATH
# Don't forget to place git-lfs binary on the PATH below if you want to enable
# Git LFS support
#Environment=PATH=/path/to/git/bin:/bin:/sbin:/usr/bin:/usr/sbin
-# If you want to bind Gitea to a port below 1024, uncomment
-# the two values below, or use socket activation to pass Gitea its ports as above
+# If you want to bind Forgejo to a port below 1024, uncomment
+# the two values below, or use socket activation to pass Forgejo its ports as above
###
#CapabilityBoundingSet=CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_BIND_SERVICE
###
# In some cases, when using CapabilityBoundingSet and AmbientCapabilities option, you may want to
-# set the following value to false to allow capabilities to be applied on gitea process. The following
-# value if set to true sandboxes gitea service and prevent any processes from running with privileges
+# set the following value to false to allow capabilities to be applied on Forgejo process. The following
+# value if set to true sandboxes Forgejo service and prevent any processes from running with privileges
# in the host user namespace.
###
#PrivateUsers=false
diff --git a/contrib/upgrade.sh b/contrib/upgrade.sh
index 4b166a02a0..4240b5694f 100755
--- a/contrib/upgrade.sh
+++ b/contrib/upgrade.sh
@@ -1,42 +1,42 @@
#!/usr/bin/env bash
-# This is an update script for gitea installed via the binary distribution
-# from dl.gitea.com on linux as systemd service. It performs a backup and updates
-# Gitea in place.
-# NOTE: This adds the GPG Signing Key of the Gitea maintainers to the keyring.
+# This is an update script for forgejo installed via the binary distribution
+# from codeberg.org/forgejo/forgejo on linux as systemd service. It
+# performs a backup and updates Forgejo in place.
+# NOTE: This adds the GPG Signing Key of the Forgejo maintainers to the keyring.
# Depends on: bash, curl, xz, sha256sum. optionally jq, gpg
# See section below for available environment vars.
# When no version is specified, updates to the latest release.
# Examples:
# upgrade.sh 1.15.10
-# giteahome=/opt/gitea giteaconf=$giteahome/app.ini upgrade.sh
+# forgejohome=/opt/forgejo forgejoconf=$forgejohome/app.ini upgrade.sh
-# Check if gitea service is running
-if ! pidof gitea &> /dev/null; then
- echo "Error: gitea is not running."
+# Check if forgejo service is running
+if ! pidof forgejo &> /dev/null; then
+ echo "Error: forgejo is not running."
exit 1
fi
-# Continue with rest of the script if gitea is running
-echo "Gitea is running. Continuing with rest of script..."
+# Continue with rest of the script if forgejo is running
+echo "Forgejo is running. Continuing with rest of script..."
# apply variables from environment
-: "${giteabin:="/usr/local/bin/gitea"}"
-: "${giteahome:="/var/lib/gitea"}"
-: "${giteaconf:="/etc/gitea/app.ini"}"
-: "${giteauser:="git"}"
+: "${forgejobin:="/usr/local/bin/forgejo"}"
+: "${forgejohome:="/var/lib/forgejo"}"
+: "${forgejoconf:="/etc/forgejo/app.ini"}"
+: "${forgejouser:="git"}"
: "${sudocmd:="sudo"}"
: "${arch:="linux-amd64"}"
-: "${service_start:="$sudocmd systemctl start gitea"}"
-: "${service_stop:="$sudocmd systemctl stop gitea"}"
-: "${service_status:="$sudocmd systemctl status gitea"}"
-: "${backupopts:=""}" # see `gitea dump --help` for available options
+: "${service_start:="$sudocmd systemctl start forgejo"}"
+: "${service_stop:="$sudocmd systemctl stop forgejo"}"
+: "${service_status:="$sudocmd systemctl status forgejo"}"
+: "${backupopts:=""}" # see `forgejo dump --help` for available options
-function giteacmd {
+function forgejocmd {
if [[ $sudocmd = "su" ]]; then
# `-c` only accept one string as argument.
- "$sudocmd" - "$giteauser" -c "$(printf "%q " "$giteabin" "--config" "$giteaconf" "--work-path" "$giteahome" "$@")"
+ "$sudocmd" - "$forgejouser" -c "$(printf "%q " "$forgejobin" "--config" "$forgejoconf" "--work-path" "$forgejohome" "$@")"
else
- "$sudocmd" --user "$giteauser" "$giteabin" --config "$giteaconf" --work-path "$giteahome" "$@"
+ "$sudocmd" --user "$forgejouser" "$forgejobin" --config "$forgejoconf" --work-path "$forgejohome" "$@"
fi
}
@@ -49,7 +49,7 @@ function require {
# parse command line arguments
while true; do
case "$1" in
- -v | --version ) giteaversion="$2"; shift 2 ;;
+ -v | --version ) forgejoversion="$2"; shift 2 ;;
-y | --yes ) no_confirm="yes"; shift ;;
--ignore-gpg) ignore_gpg="yes"; shift ;;
"" | -- ) shift; break ;;
@@ -65,9 +65,9 @@ if [[ -f /etc/os-release ]]; then
if [[ "$os_release" =~ "OpenWrt" ]]; then
sudocmd="su"
- service_start="/etc/init.d/gitea start"
- service_stop="/etc/init.d/gitea stop"
- service_status="/etc/init.d/gitea status"
+ service_start="/etc/init.d/forgejo start"
+ service_stop="/etc/init.d/forgejo stop"
+ service_status="/etc/init.d/forgejo status"
else
require systemctl
fi
@@ -76,31 +76,31 @@ fi
require curl xz sha256sum "$sudocmd"
# select version to install
-if [[ -z "${giteaversion:-}" ]]; then
+if [[ -z "${forgejoversion:-}" ]]; then
require jq
- giteaversion=$(curl --connect-timeout 10 -sL https://dl.gitea.com/gitea/version.json | jq -r .latest.version)
- echo "Latest available version is $giteaversion"
+ forgejoversion=$(curl --connect-timeout 10 -sL 'https://codeberg.org/api/v1/repos/forgejo/forgejo/releases?draft=false&pre-release=false&limit=1' -H 'accept: application/json' | jq -r '.[0].tag_name | sub("v"; "")')
+ echo "Latest available version is $forgejoversion"
fi
# confirm update
echo "Checking currently installed version..."
-current=$(giteacmd --version | cut -d ' ' -f 3)
-[[ "$current" == "$giteaversion" ]] && echo "$current is already installed, stopping." && exit 1
+current=$(forgejocmd --version | cut -d ' ' -f 3)
+[[ "$current" == "$forgejoversion" ]] && echo "$current is already installed, stopping." && exit 1
if [[ -z "${no_confirm:-}" ]]; then
- echo "Make sure to read the changelog first: https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md"
- echo "Are you ready to update Gitea from ${current} to ${giteaversion}? (y/N)"
+ echo "Make sure to read the changelog first: https://codeberg.org/forgejo/forgejo/src/branch/forgejo/CHANGELOG.md"
+ echo "Are you ready to update forgejo from ${current} to ${forgejoversion}? (y/N)"
read -r confirm
[[ "$confirm" == "y" ]] || [[ "$confirm" == "Y" ]] || exit 1
fi
-echo "Upgrading gitea from $current to $giteaversion ..."
+echo "Upgrading forgejo from $current to $forgejoversion ..."
pushd "$(pwd)" &>/dev/null
-cd "$giteahome" # needed for gitea dump later
+cd "$forgejohome" # needed for forgejo dump later
# download new binary
-binname="gitea-${giteaversion}-${arch}"
-binurl="https://dl.gitea.com/gitea/${giteaversion}/${binname}.xz"
+binname="forgejo-${forgejoversion}-${arch}"
+binurl="https://codeberg.org/forgejo/forgejo/releases/download/v${forgejoversion}/${binname}.xz"
echo "Downloading $binurl..."
curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.sha256,.asc}"
@@ -108,28 +108,28 @@ curl --connect-timeout 10 --silent --show-error --fail --location -O "$binurl{,.
sha256sum -c "${binname}.xz.sha256"
if [[ -z "${ignore_gpg:-}" ]]; then
require gpg
- gpg --keyserver keys.openpgp.org --recv 7C9E68152594688862D62AF62D9AE806EC1592E2
+ gpg --keyserver keys.openpgp.org --recv EB114F5E6C0DC2BCDD183550A4B61A2DC5923710
gpg --verify "${binname}.xz.asc" "${binname}.xz" || { echo 'Signature does not match'; exit 1; }
fi
rm "${binname}".xz.{sha256,asc}
# unpack binary + make executable
xz --decompress --force "${binname}.xz"
-chown "$giteauser" "$binname"
+chown "$forgejouser" "$binname"
chmod +x "$binname"
-# stop gitea, create backup, replace binary, restart gitea
-echo "Flushing gitea queues at $(date)"
-giteacmd manager flush-queues
-echo "Stopping gitea at $(date)"
+# stop forgejo, create backup, replace binary, restart forgejo
+echo "Flushing forgejo queues at $(date)"
+forgejocmd manager flush-queues
+echo "Stopping forgejo at $(date)"
$service_stop
-echo "Creating backup in $giteahome"
-giteacmd dump $backupopts
-echo "Updating binary at $giteabin"
-cp -f "$giteabin" "$giteabin.bak" && mv -f "$binname" "$giteabin"
+echo "Creating backup in $forgejohome"
+forgejocmd dump $backupopts
+echo "Updating binary at $forgejobin"
+cp -f "$forgejobin" "$forgejobin.bak" && mv -f "$binname" "$forgejobin"
$service_start
$service_status
-echo "Upgrade to $giteaversion successful!"
+echo "Upgrade to $forgejoversion successful!"
popd
diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini
index 99d539cf34..2663e3c01f 100644
--- a/custom/conf/app.example.ini
+++ b/custom/conf/app.example.ini
@@ -365,7 +365,7 @@ USER = root
;; SQLite Configuration
;;
;DB_TYPE = sqlite3
-;PATH= ; defaults to data/gitea.db
+;PATH= ; defaults to data/forgejo.db
;SQLITE_TIMEOUT = ; Query timeout defaults to: 500
;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode
;;
@@ -795,6 +795,11 @@ LEVEL = Info
;; Every new user will have restricted permissions depending on this setting
;DEFAULT_USER_IS_RESTRICTED = false
;;
+;; Users will be able to use dots when choosing their username. Disabling this is
+;; helpful if your usersare having issues with e.g. RSS feeds or advanced third-party
+;; extensions that use strange regex patterns.
+; ALLOW_DOTS_IN_USERNAMES = true
+;;
;; Either "public", "limited" or "private", default is "public"
;; Limited is for users visible only to signed users
;; Private is for users visible only to members of their organizations
@@ -2541,9 +2546,8 @@ LEVEL = Info
; [actions]
;; Enable/Disable actions capabilities
;ENABLED = false
-;;
-;; Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
-;DEFAULT_ACTIONS_URL = https://gitea.com
+;; Default address to get action plugins, e.g. the default value means downloading from "https://code.forgejo.org/actions/checkout" for "uses: actions/checkout@v3"
+;DEFAULT_ACTIONS_URL = https://code.forgejo.org
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
diff --git a/docker/root/etc/s6/gitea/setup b/docker/root/etc/s6/gitea/setup
index d8f6a3b319..958d50a798 100755
--- a/docker/root/etc/s6/gitea/setup
+++ b/docker/root/etc/s6/gitea/setup
@@ -24,7 +24,7 @@ if [ ! -f ${GITEA_CUSTOM}/conf/app.ini ]; then
fi
# Substitute the environment variables in the template
- APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
+ APP_NAME=${APP_NAME:-"Forgejo: Beyond coding. We forge."} \
RUN_MODE=${RUN_MODE:-"prod"} \
DOMAIN=${DOMAIN:-"localhost"} \
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
diff --git a/docker/rootless/usr/local/bin/docker-setup.sh b/docker/rootless/usr/local/bin/docker-setup.sh
index feab02a379..b480685863 100755
--- a/docker/rootless/usr/local/bin/docker-setup.sh
+++ b/docker/rootless/usr/local/bin/docker-setup.sh
@@ -26,7 +26,7 @@ if [ ! -f ${GITEA_APP_INI} ]; then
fi
# Substitute the environment variables in the template
- APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
+ APP_NAME=${APP_NAME:-"Forgejo: Beyond coding. We forge."} \
RUN_MODE=${RUN_MODE:-"prod"} \
RUN_USER=${USER:-"git"} \
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \
diff --git a/main.go b/main.go
index 49093eb8a7..8fac94eb44 100644
--- a/main.go
+++ b/main.go
@@ -50,11 +50,20 @@ func init() {
originalSubcommandHelpTemplate = cli.SubcommandHelpTemplate
}
+func forgejoEnv() {
+ for _, k := range []string{"CUSTOM", "WORK_DIR"} {
+ if v, ok := os.LookupEnv("FORGEJO_" + k); ok {
+ os.Setenv("GITEA_"+k, v)
+ }
+ }
+}
+
func main() {
+ forgejoEnv()
app := cli.NewApp()
- app.Name = "Gitea"
- app.Usage = "A painless self-hosted Git service"
- app.Description = `By default, gitea will start serving using the webserver with no
+ app.Name = "Forgejo"
+ app.Usage = "Beyond coding. We forge."
+ app.Description = `By default, forgejo will start serving using the webserver with no
arguments - which can alternatively be run by running the subcommand web.`
app.Version = Version + formatBuiltWith()
app.Commands = []cli.Command{
@@ -180,6 +189,9 @@ func adjustHelpTemplate(originalTemplate string) string {
if _, ok := os.LookupEnv("GITEA_CUSTOM"); ok {
overridden = "(GITEA_CUSTOM)"
}
+ if _, ok := os.LookupEnv("FORGEJO_CUSTOM"); ok {
+ overridden = "(FORGEJO_CUSTOM)"
+ }
return fmt.Sprintf(`%s
DEFAULT CONFIGURATION:
diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go
index a73db81f26..7f431db7d7 100644
--- a/models/migrations/migrations.go
+++ b/models/migrations/migrations.go
@@ -546,7 +546,7 @@ func EnsureUpToDate(x *xorm.Engine) error {
expected := ExpectedVersion()
if currentDB != expected {
- return fmt.Errorf(`Current database version %d is not equal to the expected version %d. Please run "gitea [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
+ return fmt.Errorf(`Current database version %d is not equal to the expected version %d. Please run "forgejo [--config /path/to/app.ini] migrate" to update the database version`, currentDB, expected)
}
return nil
diff --git a/models/user/user.go b/models/user/user.go
index 2077d55f51..3baf7152a9 100644
--- a/models/user/user.go
+++ b/models/user/user.go
@@ -548,6 +548,7 @@ var (
"user",
"v2",
"gitea-actions",
+ "forgejo-actions",
}
// DON'T ADD ANY NEW STUFF, WE SOLVE THIS WITH `/user/{obj}` PATHS!
diff --git a/models/user/user_system.go b/models/user/user_system.go
index f54f4e3ffb..e3f79a4baf 100644
--- a/models/user/user_system.go
+++ b/models/user/user_system.go
@@ -37,9 +37,9 @@ func NewReplaceUser(name string) *User {
const (
ActionsUserID = -2
- ActionsUserName = "gitea-actions"
- ActionsFullName = "Gitea Actions"
- ActionsEmail = "teabot@gitea.io"
+ ActionsUserName = "forgejo-actions"
+ ActionsFullName = "Forgejo Actions"
+ ActionsEmail = "noreply@forgejo.org"
)
// NewActionsUser creates and returns a fake user for running the actions.
diff --git a/modules/context/api.go b/modules/context/api.go
index 3c4d020413..830c651c6f 100644
--- a/modules/context/api.go
+++ b/modules/context/api.go
@@ -205,13 +205,20 @@ func (ctx *APIContext) SetLinkHeader(total, pageSize int) {
}
}
+func getOtpHeader(header http.Header) string {
+ otpHeader := header.Get("X-Gitea-OTP")
+ if forgejoHeader := header.Get("X-Forgejo-OTP"); forgejoHeader != "" {
+ otpHeader = forgejoHeader
+ }
+ return otpHeader
+}
+
// CheckForOTP validates OTP
func (ctx *APIContext) CheckForOTP() {
if skip, ok := ctx.Data["SkipLocalTwoFA"]; ok && skip.(bool) {
return // Skip 2FA
}
- otpHeader := ctx.Req.Header.Get("X-Gitea-OTP")
twofa, err := auth.GetTwoFactorByUID(ctx.Doer.ID)
if err != nil {
if auth.IsErrTwoFactorNotEnrolled(err) {
@@ -220,7 +227,7 @@ func (ctx *APIContext) CheckForOTP() {
ctx.Error(http.StatusInternalServerError, "GetTwoFactorByUID", err)
return
}
- ok, err := twofa.ValidateTOTP(otpHeader)
+ ok, err := twofa.ValidateTOTP(getOtpHeader(ctx.Req.Header))
if err != nil {
ctx.Error(http.StatusInternalServerError, "ValidateTOTP", err)
return
diff --git a/modules/context/api_forgejo_test.go b/modules/context/api_forgejo_test.go
new file mode 100644
index 0000000000..b85de55904
--- /dev/null
+++ b/modules/context/api_forgejo_test.go
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: MIT
+
+package context
+
+import (
+ "net/http"
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestGetOtpHeader(t *testing.T) {
+ header := http.Header{}
+ assert.EqualValues(t, "", getOtpHeader(header))
+ // Gitea
+ giteaOtp := "123456"
+ header.Set("X-Gitea-OTP", giteaOtp)
+ assert.EqualValues(t, giteaOtp, getOtpHeader(header))
+ // Forgejo has precedence
+ forgejoOtp := "abcdef"
+ header.Set("X-Forgejo-OTP", forgejoOtp)
+ assert.EqualValues(t, forgejoOtp, getOtpHeader(header))
+}
diff --git a/modules/httpcache/httpcache.go b/modules/httpcache/httpcache.go
index 001ac06415..79facbc15e 100644
--- a/modules/httpcache/httpcache.go
+++ b/modules/httpcache/httpcache.go
@@ -30,6 +30,7 @@ func SetCacheControlInHeader(h http.Header, maxAge time.Duration, additionalDire
// to remind users they are using non-prod setting.
h.Set("X-Gitea-Debug", "RUN_MODE="+setting.RunMode)
+ h.Set("X-Forgejo-Debug", "RUN_MODE="+setting.RunMode)
}
h.Set("Cache-Control", strings.Join(append(directives, additionalDirectives...), ", "))
diff --git a/modules/httpcache/httpcache_test.go b/modules/httpcache/httpcache_test.go
index d81f06097c..65a8a9b8fb 100644
--- a/modules/httpcache/httpcache_test.go
+++ b/modules/httpcache/httpcache_test.go
@@ -18,6 +18,9 @@ func countFormalHeaders(h http.Header) (c int) {
if strings.HasPrefix(k, "X-Gitea-") {
continue
}
+ if strings.HasPrefix(k, "X-Forgejo-") {
+ continue
+ }
c++
}
return c
diff --git a/modules/setting/actions.go b/modules/setting/actions.go
index 1c8075cd6c..c0990b9b6f 100644
--- a/modules/setting/actions.go
+++ b/modules/setting/actions.go
@@ -16,7 +16,7 @@ var (
DefaultActionsURL string `ini:"DEFAULT_ACTIONS_URL"`
}{
Enabled: false,
- DefaultActionsURL: "https://gitea.com",
+ DefaultActionsURL: "https://code.forgejo.org",
}
)
diff --git a/modules/setting/config_env.go b/modules/setting/config_env.go
index 6348803705..4ec2e61289 100644
--- a/modules/setting/config_env.go
+++ b/modules/setting/config_env.go
@@ -75,19 +75,21 @@ func decodeEnvSectionKey(encoded string) (ok bool, section, key string) {
// decodeEnvironmentKey decode the environment key to section and key
// The environment key is in the form of GITEA__SECTION__KEY or GITEA__SECTION__KEY__FILE
-func decodeEnvironmentKey(prefixGitea, suffixFile, envKey string) (ok bool, section, key string, useFileValue bool) {
- if !strings.HasPrefix(envKey, prefixGitea) {
- return false, "", "", false
- }
+func decodeEnvironmentKey(prefixRegexp *regexp.Regexp, suffixFile, envKey string) (ok bool, section, key string, useFileValue bool) {
if strings.HasSuffix(envKey, suffixFile) {
useFileValue = true
envKey = envKey[:len(envKey)-len(suffixFile)]
}
- ok, section, key = decodeEnvSectionKey(envKey[len(prefixGitea):])
+ loc := prefixRegexp.FindStringIndex(envKey)
+ if loc == nil {
+ return false, "", "", false
+ }
+ ok, section, key = decodeEnvSectionKey(envKey[loc[1]:])
return ok, section, key, useFileValue
}
func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, envs []string) (changed bool) {
+ prefixRegexp := regexp.MustCompile(prefixGitea)
for _, kv := range envs {
idx := strings.IndexByte(kv, '=')
if idx < 0 {
@@ -97,7 +99,7 @@ func EnvironmentToConfig(cfg ConfigProvider, prefixGitea, suffixFile string, env
// parse the environment variable to config section name and key name
envKey := kv[:idx]
envValue := kv[idx+1:]
- ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixGitea, suffixFile, envKey)
+ ok, sectionName, keyName, useFileValue := decodeEnvironmentKey(prefixRegexp, suffixFile, envKey)
if !ok {
continue
}
diff --git a/modules/setting/config_env_test.go b/modules/setting/config_env_test.go
index d574554bcc..41c4b4ac2a 100644
--- a/modules/setting/config_env_test.go
+++ b/modules/setting/config_env_test.go
@@ -5,6 +5,7 @@ package setting
import (
"os"
+ "regexp"
"testing"
"github.com/stretchr/testify/assert"
@@ -33,7 +34,7 @@ func TestDecodeEnvSectionKey(t *testing.T) {
}
func TestDecodeEnvironmentKey(t *testing.T) {
- prefix := "GITEA__"
+ prefix := regexp.MustCompile("^(FORGEJO|GITEA)__")
suffix := "__FILE"
ok, section, key, file := decodeEnvironmentKey(prefix, suffix, "SEC__KEY")
@@ -54,6 +55,12 @@ func TestDecodeEnvironmentKey(t *testing.T) {
assert.Equal(t, "KEY", key)
assert.False(t, file)
+ ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "FORGEJO__SEC__KEY")
+ assert.True(t, ok)
+ assert.Equal(t, "sec", section)
+ assert.Equal(t, "KEY", key)
+ assert.False(t, file)
+
// with "__FILE" suffix, it doesn't support to write "[sec].FILE" to config (no such key FILE is used in Gitea)
// but it could be fixed in the future by adding a new suffix like "__VALUE" (no such key VALUE is used in Gitea either)
ok, section, key, file = decodeEnvironmentKey(prefix, suffix, "GITEA__SEC__FILE")
@@ -72,7 +79,7 @@ func TestDecodeEnvironmentKey(t *testing.T) {
func TestEnvironmentToConfig(t *testing.T) {
cfg, _ := NewConfigProviderFromData("")
- changed := EnvironmentToConfig(cfg, "GITEA__", "__FILE", nil)
+ changed := EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", nil)
assert.False(t, changed)
cfg, err := NewConfigProviderFromData(`
@@ -81,16 +88,16 @@ key = old
`)
assert.NoError(t, err)
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
+ changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key=new"})
assert.True(t, changed)
assert.Equal(t, "new", cfg.Section("sec").Key("key").String())
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key=new"})
+ changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key=new"})
assert.False(t, changed)
tmpFile := t.TempDir() + "/the-file"
_ = os.WriteFile(tmpFile, []byte("value-from-file"), 0o644)
- changed = EnvironmentToConfig(cfg, "GITEA__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
+ changed = EnvironmentToConfig(cfg, "^(FORGEJO|GITEA)__", "__FILE", []string{"GITEA__sec__key__FILE=" + tmpFile})
assert.True(t, changed)
assert.Equal(t, "value-from-file", cfg.Section("sec").Key("key").String())
}
diff --git a/modules/setting/database.go b/modules/setting/database.go
index 7a7c7029a4..8f609743c1 100644
--- a/modules/setting/database.go
+++ b/modules/setting/database.go
@@ -79,7 +79,7 @@ func loadDBSetting(rootCfg ConfigProvider) {
log.Error("Deprecated database mysql charset utf8 support, please use utf8mb4 or convert utf8 to utf8mb4.")
}
- Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "gitea.db"))
+ Database.Path = sec.Key("PATH").MustString(filepath.Join(AppDataPath, "forgejo.db"))
Database.Timeout = sec.Key("SQLITE_TIMEOUT").MustInt(500)
Database.SQLiteJournalMode = sec.Key("SQLITE_JOURNAL_MODE").MustString("")
diff --git a/modules/setting/repository.go b/modules/setting/repository.go
index 42ffb99138..2d15a58937 100644
--- a/modules/setting/repository.go
+++ b/modules/setting/repository.go
@@ -276,7 +276,7 @@ func loadRepositoryFrom(rootCfg ConfigProvider) {
Repository.GoGetCloneURLProtocol = sec.Key("GO_GET_CLONE_URL_PROTOCOL").MustString("https")
Repository.MaxCreationLimit = sec.Key("MAX_CREATION_LIMIT").MustInt(-1)
Repository.DefaultBranch = sec.Key("DEFAULT_BRANCH").MustString(Repository.DefaultBranch)
- RepoRootPath = sec.Key("ROOT").MustString(path.Join(AppDataPath, "gitea-repositories"))
+ RepoRootPath = sec.Key("ROOT").MustString(path.Join(AppDataPath, "forgejo-repositories"))
if !filepath.IsAbs(RepoRootPath) {
RepoRootPath = filepath.Join(AppWorkPath, RepoRootPath)
} else {
diff --git a/modules/setting/server.go b/modules/setting/server.go
index d937faca10..0c4e14a218 100644
--- a/modules/setting/server.go
+++ b/modules/setting/server.go
@@ -167,7 +167,7 @@ func MakeAbsoluteAssetURL(appURL, staticURLPrefix string) string {
func loadServerFrom(rootCfg ConfigProvider) {
sec := rootCfg.Section("server")
- AppName = rootCfg.Section("").Key("APP_NAME").MustString("Gitea: Git with a cup of tea")
+ AppName = rootCfg.Section("").Key("APP_NAME").MustString("Forgejo: Beyond coding. We Forge.")
Domain = sec.Key("DOMAIN").MustString("localhost")
HTTPAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0")
diff --git a/modules/setting/service.go b/modules/setting/service.go
index 03225f566b..b2cef8126e 100644
--- a/modules/setting/service.go
+++ b/modules/setting/service.go
@@ -67,6 +67,7 @@ var Service = struct {
DefaultKeepEmailPrivate bool
DefaultAllowCreateOrganization bool
DefaultUserIsRestricted bool
+ AllowDotsInUsernames bool
EnableTimetracking bool
DefaultEnableTimetracking bool
DefaultEnableDependencies bool
@@ -177,6 +178,7 @@ func loadServiceFrom(rootCfg ConfigProvider) {
Service.DefaultKeepEmailPrivate = sec.Key("DEFAULT_KEEP_EMAIL_PRIVATE").MustBool()
Service.DefaultAllowCreateOrganization = sec.Key("DEFAULT_ALLOW_CREATE_ORGANIZATION").MustBool(true)
Service.DefaultUserIsRestricted = sec.Key("DEFAULT_USER_IS_RESTRICTED").MustBool(false)
+ Service.AllowDotsInUsernames = sec.Key("ALLOW_DOTS_IN_USERNAMES").MustBool(true)
Service.EnableTimetracking = sec.Key("ENABLE_TIMETRACKING").MustBool(true)
if Service.EnableTimetracking {
Service.DefaultEnableTimetracking = sec.Key("DEFAULT_ENABLE_TIMETRACKING").MustBool(true)
diff --git a/modules/setting/setting.go b/modules/setting/setting.go
index 539eb4b197..9730dcd926 100644
--- a/modules/setting/setting.go
+++ b/modules/setting/setting.go
@@ -147,6 +147,9 @@ func SetCustomPathAndConf(providedCustom, providedConf, providedWorkPath string)
if giteaCustom, ok := os.LookupEnv("GITEA_CUSTOM"); ok {
CustomPath = giteaCustom
}
+ if forgejoCustom, ok := os.LookupEnv("FORGEJO_CUSTOM"); ok {
+ CustomPath = forgejoCustom
+ }
if len(providedCustom) != 0 {
CustomPath = providedCustom
}
diff --git a/modules/setting/ui.go b/modules/setting/ui.go
index 41438db40d..c8ad75856e 100644
--- a/modules/setting/ui.go
+++ b/modules/setting/ui.go
@@ -76,11 +76,11 @@ var UI = struct {
CodeCommentLines: 4,
ReactionMaxUserNum: 10,
MaxDisplayFileSize: 8388608,
- DefaultTheme: `auto`,
- Themes: []string{`auto`, `gitea`, `arc-green`},
+ DefaultTheme: `forgejo-auto`,
+ Themes: []string{`forgejo-auto`, `forgejo-light`, `forgejo-dark`, `auto`, `gitea`, `arc-green`},
Reactions: []string{`+1`, `-1`, `laugh`, `hooray`, `confused`, `heart`, `rocket`, `eyes`},
- CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`},
- CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:"},
+ CustomEmojis: []string{`git`, `gitea`, `codeberg`, `gitlab`, `github`, `gogs`, `forgejo`},
+ CustomEmojisMap: map[string]string{"git": ":git:", "gitea": ":gitea:", "codeberg": ":codeberg:", "gitlab": ":gitlab:", "github": ":github:", "gogs": ":gogs:", "forgejo": ":forgejo:"},
Notification: struct {
MinTimeout time.Duration
TimeoutStep time.Duration
@@ -123,9 +123,9 @@ var UI = struct {
Description string
Keywords string
}{
- Author: "Gitea - Git with a cup of tea",
- Description: "Gitea (Git with a cup of tea) is a painless self-hosted Git service written in Go",
- Keywords: "go,git,self-hosted,gitea",
+ Author: "Forgejo – Beyond coding. We forge.",
+ Description: "Forgejo is a self-hosted lightweight software forge. Easy to install and low maintenance, it just does the job.",
+ Keywords: "git,forge,forgejo",
},
}
diff --git a/modules/setting/webhook.go b/modules/setting/webhook.go
index c01261dbbd..b56c55c439 100644
--- a/modules/setting/webhook.go
+++ b/modules/setting/webhook.go
@@ -35,7 +35,7 @@ func loadWebhookFrom(rootCfg ConfigProvider) {
Webhook.DeliverTimeout = sec.Key("DELIVER_TIMEOUT").MustInt(5)
Webhook.SkipTLSVerify = sec.Key("SKIP_TLS_VERIFY").MustBool()
Webhook.AllowedHostList = sec.Key("ALLOWED_HOST_LIST").MustString("")
- Webhook.Types = []string{"gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"}
+ Webhook.Types = []string{"forgejo", "gitea", "gogs", "slack", "discord", "dingtalk", "telegram", "msteams", "feishu", "matrix", "wechatwork", "packagist"}
Webhook.PagingNum = sec.Key("PAGING_NUM").MustInt(10)
Webhook.ProxyURL = sec.Key("PROXY_URL").MustString("")
if Webhook.ProxyURL != "" {
diff --git a/modules/structs/hook.go b/modules/structs/hook.go
index cd91d4bc46..120df34915 100644
--- a/modules/structs/hook.go
+++ b/modules/structs/hook.go
@@ -40,7 +40,7 @@ type CreateHookOptionConfig map[string]string
// CreateHookOption options when create a hook
type CreateHookOption struct {
// required: true
- // enum: dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
+ // enum: forgejo,dingtalk,discord,gitea,gogs,msteams,slack,telegram,feishu,wechatwork,packagist
Type string `json:"type" binding:"Required"`
// required: true
Config CreateHookOptionConfig `json:"config" binding:"Required"`
diff --git a/modules/validation/helpers.go b/modules/validation/helpers.go
index 3381846b86..2f88fcbc60 100644
--- a/modules/validation/helpers.go
+++ b/modules/validation/helpers.go
@@ -92,13 +92,20 @@ func IsValidExternalTrackerURLFormat(uri string) bool {
}
var (
- validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
- invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars
+ validUsernamePatternWithDots = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
+ validUsernamePatternWithoutDots = regexp.MustCompile(`^[\da-zA-Z][-\w]*$`)
+
+ // No consecutive or trailing non-alphanumeric chars, catches both cases
+ invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`)
)
// IsValidUsername checks if username is valid
func IsValidUsername(name string) bool {
// It is difficult to find a single pattern that is both readable and effective,
// but it's easier to use positive and negative checks.
- return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name)
+ if setting.Service.AllowDotsInUsernames {
+ return validUsernamePatternWithDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
+ }
+
+ return validUsernamePatternWithoutDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
}
diff --git a/modules/validation/helpers_test.go b/modules/validation/helpers_test.go
index 52f383f698..a1bdf2a29c 100644
--- a/modules/validation/helpers_test.go
+++ b/modules/validation/helpers_test.go
@@ -155,7 +155,8 @@ func Test_IsValidExternalTrackerURLFormat(t *testing.T) {
}
}
-func TestIsValidUsername(t *testing.T) {
+func TestIsValidUsernameAllowDots(t *testing.T) {
+ setting.Service.AllowDotsInUsernames = true
tests := []struct {
arg string
want bool
@@ -185,3 +186,31 @@ func TestIsValidUsername(t *testing.T) {
})
}
}
+
+func TestIsValidUsernameBanDots(t *testing.T) {
+ setting.Service.AllowDotsInUsernames = false
+ defer func() {
+ setting.Service.AllowDotsInUsernames = true
+ }()
+
+ tests := []struct {
+ arg string
+ want bool
+ }{
+ {arg: "a", want: true},
+ {arg: "abc", want: true},
+ {arg: "0.b-c", want: false},
+ {arg: "a.b-c_d", want: false},
+ {arg: ".abc", want: false},
+ {arg: "abc.", want: false},
+ {arg: "a..bc", want: false},
+ {arg: "a...bc", want: false},
+ {arg: "a.-bc", want: false},
+ {arg: "a._bc", want: false},
+ }
+ for _, tt := range tests {
+ t.Run(tt.arg, func(t *testing.T) {
+ assert.Equalf(t, tt.want, IsValidUsername(tt.arg), "IsValidUsername[AllowDotsInUsernames=false](%v)", tt.arg)
+ })
+ }
+}
diff --git a/modules/web/middleware/binding.go b/modules/web/middleware/binding.go
index 8b74a864d9..071a837a78 100644
--- a/modules/web/middleware/binding.go
+++ b/modules/web/middleware/binding.go
@@ -8,6 +8,7 @@ import (
"reflect"
"strings"
+ "code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/translation"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/modules/validation"
@@ -135,7 +136,11 @@ func Validate(errs binding.Errors, data map[string]interface{}, f Form, l transl
case validation.ErrRegexPattern:
data["ErrorMsg"] = trName + l.Tr("form.regex_pattern_error", errs[0].Message)
case validation.ErrUsername:
- data["ErrorMsg"] = trName + l.Tr("form.username_error")
+ if setting.Service.AllowDotsInUsernames {
+ data["ErrorMsg"] = trName + l.Tr("form.username_error")
+ } else {
+ data["ErrorMsg"] = trName + l.Tr("form.username_error_no_dots")
+ }
case validation.ErrInvalidGroupTeamMap:
data["ErrorMsg"] = trName + l.Tr("form.invalid_group_team_map_error", errs[0].Message)
default:
diff --git a/modules/webhook/type.go b/modules/webhook/type.go
index 7042d391b7..7f427f2ea8 100644
--- a/modules/webhook/type.go
+++ b/modules/webhook/type.go
@@ -72,6 +72,7 @@ type HookType = string
// Types of webhooks
const (
+ FORGEJO HookType = "forgejo"
GITEA HookType = "gitea"
GOGS HookType = "gogs"
SLACK HookType = "slack"
diff --git a/options/locales/gitea_en-US.ini b/options/locales/gitea_en-US.ini
index 25456d0493..d7e5aa4648 100644
--- a/options/locales/gitea_en-US.ini
+++ b/options/locales/gitea_en-US.ini
@@ -285,6 +285,7 @@ default_allow_create_organization = Allow Creation of Organizations by Default
default_allow_create_organization_popup = Allow new user accounts to create organizations by default.
default_enable_timetracking = Enable Time Tracking by Default
default_enable_timetracking_popup = Enable time tracking for new repositories by default.
+allow_dots_in_usernames = Allow users to use dots in their usernames. Doesn't affect existing accounts.
no_reply_address = Hidden Email Domain
no_reply_address_helper = Domain name for users with a hidden email address. For example, the username 'joe' will be logged in Git as 'joe@noreply.example.org' if the hidden email domain is set to 'noreply.example.org'.
password_algorithm = Password Hash Algorithm
@@ -521,6 +522,7 @@ include_error = ` must contain substring "%s".`
glob_pattern_error = ` glob pattern is invalid: %s.`
regex_pattern_error = ` regex pattern is invalid: %s.`
username_error = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-'), underscore ('_') and dot ('.'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.`
+username_error_no_dots = ` can only contain alphanumeric chars ('0-9','a-z','A-Z'), dash ('-') and underscore ('_'). It cannot begin or end with non-alphanumeric chars, and consecutive non-alphanumeric chars are also forbidden.`
invalid_group_team_map_error = ` mapping is invalid: %s`
unknown_error = Unknown error:
captcha_incorrect = The CAPTCHA code is incorrect.
diff --git a/public/img/apple-touch-icon.png b/public/img/apple-touch-icon.png
index 0c803d35dc..1f6c1544f8 100644
Binary files a/public/img/apple-touch-icon.png and b/public/img/apple-touch-icon.png differ
diff --git a/public/img/avatar_default.png b/public/img/avatar_default.png
index 129967112d..f335e51dad 100644
Binary files a/public/img/avatar_default.png and b/public/img/avatar_default.png differ
diff --git a/public/img/emoji/forgejo.png b/public/img/emoji/forgejo.png
new file mode 100644
index 0000000000..f335e51dad
Binary files /dev/null and b/public/img/emoji/forgejo.png differ
diff --git a/public/img/failed.png b/public/img/failed.png
deleted file mode 100644
index b37545f90c..0000000000
Binary files a/public/img/failed.png and /dev/null differ
diff --git a/public/img/favicon.png b/public/img/favicon.png
index dcd4edb1a3..eda0347eff 100644
Binary files a/public/img/favicon.png and b/public/img/favicon.png differ
diff --git a/public/img/favicon.svg b/public/img/favicon.svg
index afeeacb77c..804b05e284 100644
--- a/public/img/favicon.svg
+++ b/public/img/favicon.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/img/forgejo-loading.svg b/public/img/forgejo-loading.svg
new file mode 100644
index 0000000000..919552ebb5
--- /dev/null
+++ b/public/img/forgejo-loading.svg
@@ -0,0 +1,14 @@
+
diff --git a/public/img/forgejo.svg b/public/img/forgejo.svg
new file mode 100644
index 0000000000..804b05e284
--- /dev/null
+++ b/public/img/forgejo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/img/gitea-original.svg b/public/img/gitea-original.svg
new file mode 100644
index 0000000000..dca9b4f4db
--- /dev/null
+++ b/public/img/gitea-original.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/public/img/gitea.svg b/public/img/gitea.svg
index dca9b4f4db..804b05e284 100644
--- a/public/img/gitea.svg
+++ b/public/img/gitea.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/public/img/loading.png b/public/img/loading.png
deleted file mode 100644
index c5ba3d9cd7..0000000000
Binary files a/public/img/loading.png and /dev/null differ
diff --git a/public/img/logo.png b/public/img/logo.png
index c7971f9183..1b2d9b4023 100644
Binary files a/public/img/logo.png and b/public/img/logo.png differ
diff --git a/public/img/logo.svg b/public/img/logo.svg
index afeeacb77c..804b05e284 100644
--- a/public/img/logo.svg
+++ b/public/img/logo.svg
@@ -1 +1 @@
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go
index be66cc5240..49e77ee0cb 100644
--- a/routers/api/v1/api.go
+++ b/routers/api/v1/api.go
@@ -56,7 +56,7 @@
// description: Sudo API request as the user provided as the key. Admin privileges are required.
// TOTPHeader:
// type: apiKey
-// name: X-GITEA-OTP
+// name: X-FORGEJO-OTP
// in: header
// description: Must be used in combination with BasicAuth if two-factor authentication is enabled.
//
@@ -715,7 +715,7 @@ func Routes() *web.Route {
// setting.CORSConfig.AllowSubdomain // FIXME: the cors middleware needs allowSubdomain option
AllowedMethods: setting.CORSConfig.Methods,
AllowCredentials: setting.CORSConfig.AllowCredentials,
- AllowedHeaders: append([]string{"Authorization", "X-Gitea-OTP"}, setting.CORSConfig.Headers...),
+ AllowedHeaders: append([]string{"Authorization", "X-Gitea-OTP", "X-Forgejo-OTP"}, setting.CORSConfig.Headers...),
MaxAge: int(setting.CORSConfig.MaxAge.Seconds()),
}))
}
diff --git a/routers/api/v1/misc/nodeinfo.go b/routers/api/v1/misc/nodeinfo.go
index 319c3483e1..9e6e2e3db1 100644
--- a/routers/api/v1/misc/nodeinfo.go
+++ b/routers/api/v1/misc/nodeinfo.go
@@ -65,10 +65,10 @@ func NodeInfo(ctx *context.APIContext) {
nodeInfo := &structs.NodeInfo{
Version: "2.1",
Software: structs.NodeInfoSoftware{
- Name: "gitea",
+ Name: "forgejo",
Version: setting.AppVer,
- Repository: "https://github.com/go-gitea/gitea.git",
- Homepage: "https://gitea.io/",
+ Repository: "https://codeberg.org/forgejo/forgejo.git",
+ Homepage: "https://forgejo.org/",
},
Protocols: []string{"activitypub"},
Services: structs.NodeInfoServices{
diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go
index 2b468d6e73..5968a6b40d 100644
--- a/routers/api/v1/repo/file.go
+++ b/routers/api/v1/repo/file.go
@@ -33,7 +33,10 @@ import (
files_service "code.gitea.io/gitea/services/repository/files"
)
-const giteaObjectTypeHeader = "X-Gitea-Object-Type"
+const (
+ giteaObjectTypeHeader = "X-Gitea-Object-Type"
+ forgejoObjectTypeHeader = "X-Forgejo-Object-Type"
+)
// GetRawFile get a file by path on a repository
func GetRawFile(ctx *context.APIContext) {
@@ -80,6 +83,7 @@ func GetRawFile(ctx *context.APIContext) {
}
ctx.RespHeader().Set(giteaObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
+ ctx.RespHeader().Set(forgejoObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
if err := common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified); err != nil {
ctx.Error(http.StatusInternalServerError, "ServeBlob", err)
@@ -129,6 +133,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
}
ctx.RespHeader().Set(giteaObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
+ ctx.RespHeader().Set(forgejoObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
// LFS Pointer files are at most 1024 bytes - so any blob greater than 1024 bytes cannot be an LFS file
if blob.Size() > 1024 {
diff --git a/routers/common/db.go b/routers/common/db.go
index 2e86fbd0fd..5ce09d88e4 100644
--- a/routers/common/db.go
+++ b/routers/common/db.go
@@ -51,7 +51,7 @@ func migrateWithSetting(x *xorm.Engine) error {
return migrations.Migrate(x)
} else if expected := migrations.ExpectedVersion(); current != expected {
log.Fatal(`"database.AUTO_MIGRATION" is disabled, but current database version %d is not equal to the expected version %d.`+
- `You can set "database.AUTO_MIGRATION" to true or migrate manually by running "gitea [--config /path/to/app.ini] migrate"`, current, expected)
+ `You can set "database.AUTO_MIGRATION" to true or migrate manually by running "forgejo [--config /path/to/app.ini] migrate"`, current, expected)
}
return nil
}
diff --git a/routers/install/install.go b/routers/install/install.go
index 16bb55b685..22cb829096 100644
--- a/routers/install/install.go
+++ b/routers/install/install.go
@@ -181,7 +181,7 @@ func checkDatabase(ctx *context.Context, form *forms.InstallForm) bool {
if err = db.InitEngine(ctx); err != nil {
if strings.Contains(err.Error(), `Unknown database type: sqlite3`) {
ctx.Data["Err_DbType"] = true
- ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://docs.gitea.io/en-us/install-from-binary/"), tplInstall, form)
+ ctx.RenderWithErr(ctx.Tr("install.sqlite3_not_available", "https://forgejo.org/download#installation-from-binary"), tplInstall, form)
} else {
ctx.Data["Err_DbSetting"] = true
ctx.RenderWithErr(ctx.Tr("install.invalid_db_setting", err), tplInstall, form)
diff --git a/routers/web/admin/config.go b/routers/web/admin/config.go
index be662c22ef..1422170924 100644
--- a/routers/web/admin/config.go
+++ b/routers/web/admin/config.go
@@ -174,10 +174,10 @@ func Config(ctx *context.Context) {
envVars := map[string]*envVar{}
if len(os.Getenv("GITEA_WORK_DIR")) > 0 {
- envVars["GITEA_WORK_DIR"] = &envVar{"GITEA_WORK_DIR", os.Getenv("GITEA_WORK_DIR")}
+ envVars["FORGEJO_WORK_DIR"] = &envVar{"GITEA_WORK_DIR", os.Getenv("GITEA_WORK_DIR")}
}
if len(os.Getenv("GITEA_CUSTOM")) > 0 {
- envVars["GITEA_CUSTOM"] = &envVar{"GITEA_CUSTOM", os.Getenv("GITEA_CUSTOM")}
+ envVars["FORGEJO_CUSTOM"] = &envVar{"GITEA_CUSTOM", os.Getenv("GITEA_CUSTOM")}
}
ctx.Data["EnvVars"] = envVars
diff --git a/routers/web/repo/webhook.go b/routers/web/repo/webhook.go
index 5139c0b091..92ea90bd3d 100644
--- a/routers/web/repo/webhook.go
+++ b/routers/web/repo/webhook.go
@@ -308,6 +308,34 @@ func editWebhook(ctx *context.Context, params webhookParams) {
ctx.Redirect(fmt.Sprintf("%s/%d", orCtx.Link, w.ID))
}
+// ForgejoHooksNewPost response for creating Forgejo webhook
+func ForgejoHooksNewPost(ctx *context.Context) {
+ createWebhook(ctx, forgejoHookParams(ctx))
+}
+
+// ForgejoHooksEditPost response for editing Forgejo webhook
+func ForgejoHooksEditPost(ctx *context.Context) {
+ editWebhook(ctx, forgejoHookParams(ctx))
+}
+
+func forgejoHookParams(ctx *context.Context) webhookParams {
+ form := web.GetForm(ctx).(*forms.NewWebhookForm)
+
+ contentType := webhook.ContentTypeJSON
+ if webhook.HookContentType(form.ContentType) == webhook.ContentTypeForm {
+ contentType = webhook.ContentTypeForm
+ }
+
+ return webhookParams{
+ Type: webhook_module.FORGEJO,
+ URL: form.PayloadURL,
+ ContentType: contentType,
+ Secret: form.Secret,
+ HTTPMethod: form.HTTPMethod,
+ WebhookForm: form.WebhookForm,
+ }
+}
+
// GiteaHooksNewPost response for creating Gitea webhook
func GiteaHooksNewPost(ctx *context.Context) {
createWebhook(ctx, giteaHookParams(ctx))
diff --git a/routers/web/web.go b/routers/web/web.go
index b17736c81a..b92fcad2ed 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -282,6 +282,7 @@ func registerRoutes(m *web.Route) {
addWebhookAddRoutes := func() {
m.Get("/{type}/new", repo.WebhooksNew)
+ m.Post("/forgejo/new", web.Bind(forms.NewWebhookForm{}), repo.ForgejoHooksNewPost)
m.Post("/gitea/new", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksNewPost)
m.Post("/gogs/new", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksNewPost)
m.Post("/slack/new", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksNewPost)
@@ -296,6 +297,7 @@ func registerRoutes(m *web.Route) {
}
addWebhookEditRoutes := func() {
+ m.Post("/forgejo/{id}", web.Bind(forms.NewWebhookForm{}), repo.ForgejoHooksEditPost)
m.Post("/gitea/{id}", web.Bind(forms.NewWebhookForm{}), repo.GiteaHooksEditPost)
m.Post("/gogs/{id}", web.Bind(forms.NewGogshookForm{}), repo.GogsHooksEditPost)
m.Post("/slack/{id}", web.Bind(forms.NewSlackHookForm{}), repo.SlackHooksEditPost)
diff --git a/services/mailer/mail.go b/services/mailer/mail.go
index 351b79b5df..030491a467 100644
--- a/services/mailer/mail.go
+++ b/services/mailer/mail.go
@@ -415,6 +415,16 @@ func generateAdditionalHeaders(ctx *mailCommentContext, reason string, recipient
"X-Gitea-Issue-ID": strconv.FormatInt(ctx.Issue.Index, 10),
"X-Gitea-Issue-Link": ctx.Issue.HTMLURL(),
+ "X-Forgejo-Reason": reason,
+ "X-Forgejo-Sender": ctx.Doer.DisplayName(),
+ "X-Forgejo-Recipient": recipient.DisplayName(),
+ "X-Forgejo-Recipient-Address": recipient.Email,
+ "X-Forgejo-Repository": repo.Name,
+ "X-Forgejo-Repository-Path": repo.FullName(),
+ "X-Forgejo-Repository-Link": repo.HTMLURL(),
+ "X-Forgejo-Issue-ID": strconv.FormatInt(ctx.Issue.Index, 10),
+ "X-Forgejo-Issue-Link": ctx.Issue.HTMLURL(),
+
"X-GitHub-Reason": reason,
"X-GitHub-Sender": ctx.Doer.DisplayName(),
"X-GitHub-Recipient": recipient.DisplayName(),
diff --git a/services/webhook/deliver.go b/services/webhook/deliver.go
index fd7a3d7fba..d13fe1c5d3 100644
--- a/services/webhook/deliver.go
+++ b/services/webhook/deliver.go
@@ -123,6 +123,10 @@ func Deliver(ctx context.Context, t *webhook_model.HookTask) error {
event := t.EventType.Event()
eventType := string(t.EventType)
+ req.Header.Add("X-Forgejo-Delivery", t.UUID)
+ req.Header.Add("X-Forgejo-Event", event)
+ req.Header.Add("X-Forgejo-Event-Type", eventType)
+ req.Header.Add("X-Forgejo-Signature", signatureSHA256)
req.Header.Add("X-Gitea-Delivery", t.UUID)
req.Header.Add("X-Gitea-Event", event)
req.Header.Add("X-Gitea-Event-Type", eventType)
diff --git a/services/webhook/webhook.go b/services/webhook/webhook.go
index 3cd9deafd8..4f77e23efc 100644
--- a/services/webhook/webhook.go
+++ b/services/webhook/webhook.go
@@ -69,7 +69,7 @@ var webhooks = map[webhook_module.HookType]*webhook{
// IsValidHookTaskType returns true if a webhook registered
func IsValidHookTaskType(name string) bool {
- if name == webhook_module.GITEA || name == webhook_module.GOGS {
+ if name == webhook_module.FORGEJO || name == webhook_module.GITEA || name == webhook_module.GOGS {
return true
}
_, ok := webhooks[name]
@@ -172,7 +172,7 @@ func PrepareWebhook(ctx context.Context, w *webhook_model.Webhook, event webhook
// Avoid sending "0 new commits" to non-integration relevant webhooks (e.g. slack, discord, etc.).
// Integration webhooks (e.g. drone) still receive the required data.
if pushEvent, ok := p.(*api.PushPayload); ok &&
- w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS &&
+ w.Type != webhook_module.FORGEJO && w.Type != webhook_module.GITEA && w.Type != webhook_module.GOGS &&
len(pushEvent.Commits) == 0 {
return nil
}
diff --git a/templates/admin/auth/edit.tmpl b/templates/admin/auth/edit.tmpl
index 801cf9e7b4..b6b26076a6 100644
--- a/templates/admin/auth/edit.tmpl
+++ b/templates/admin/auth/edit.tmpl
@@ -133,7 +133,7 @@
-
+
@@ -360,7 +360,7 @@
-
+
diff --git a/templates/admin/auth/source/ldap.tmpl b/templates/admin/auth/source/ldap.tmpl
index a2bd37be0c..6ecff413b4 100644
--- a/templates/admin/auth/source/ldap.tmpl
+++ b/templates/admin/auth/source/ldap.tmpl
@@ -106,7 +106,7 @@
-
+
diff --git a/templates/admin/auth/source/oauth.tmpl b/templates/admin/auth/source/oauth.tmpl
index aaa8b7fe2d..8e62bdfc5b 100644
--- a/templates/admin/auth/source/oauth.tmpl
+++ b/templates/admin/auth/source/oauth.tmpl
@@ -100,7 +100,7 @@
-
+
diff --git a/templates/admin/config.tmpl b/templates/admin/config.tmpl
index 2850cc8d37..e28714eb38 100644
--- a/templates/admin/config.tmpl
+++ b/templates/admin/config.tmpl
@@ -168,6 +168,8 @@
{{if .Service.DefaultKeepEmailPrivate}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
{{.locale.Tr "admin.config.default_allow_create_organization"}}
{{if .Service.DefaultAllowCreateOrganization}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
+
{{.locale.Tr "admin.config.allow_dots_in_usernames"}}
+
{{if .Service.AllowDotsInUsernames}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
{{.locale.Tr "admin.config.enable_timetracking"}}
{{if .Service.EnableTimetracking}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}}
{{if .Service.EnableTimetracking}}
diff --git a/templates/admin/hook_new.tmpl b/templates/admin/hook_new.tmpl
index 1abdd4c813..f1ec14f68c 100644
--- a/templates/admin/hook_new.tmpl
+++ b/templates/admin/hook_new.tmpl
@@ -11,8 +11,10 @@
{{.locale.Tr "admin.defaulthooks.update_webhook"}}
{{end}}
- {{if eq .HookType "gitea"}}
-

+ {{if eq .HookType "forgejo"}}
+

+ {{else if eq .HookType "gitea"}}
+

{{else if eq .HookType "gogs"}}

{{else if eq .HookType "slack"}}
@@ -37,6 +39,7 @@
+ {{template "repo/settings/webhook/forgejo" .}}
{{template "repo/settings/webhook/gitea" .}}
{{template "repo/settings/webhook/gogs" .}}
{{template "repo/settings/webhook/slack" .}}
diff --git a/templates/base/footer_content.tmpl b/templates/base/footer_content.tmpl
index f527274484..6cc4e851db 100644
--- a/templates/base/footer_content.tmpl
+++ b/templates/base/footer_content.tmpl
@@ -1,6 +1,6 @@
-
+
{{template "base/footer" .}}
diff --git a/templates/org/settings/hook_new.tmpl b/templates/org/settings/hook_new.tmpl
index 1bf74fb7ba..da1813b001 100644
--- a/templates/org/settings/hook_new.tmpl
+++ b/templates/org/settings/hook_new.tmpl
@@ -3,8 +3,10 @@