diff --git a/models/user/block.go b/models/user/block.go index e4e4756cc0f..abf4daa57d0 100644 --- a/models/user/block.go +++ b/models/user/block.go @@ -45,15 +45,20 @@ func UpdateBlockingNote(ctx context.Context, id int64, note string) error { } func IsUserBlockedBy(ctx context.Context, blockee *User, blockerIDs ...int64) bool { - if len(blockerIDs) == 0 { - return false - } - if blockee.IsAdmin { return false } - cond := builder.Eq{"user_blocking.blockee_id": blockee.ID}. + return HasBlocking(ctx, blockee.ID, blockerIDs...) +} + +// HasBlocking reports whether a blocking relationship exists regardless of the blockee's admin status. +func HasBlocking(ctx context.Context, blockeeID int64, blockerIDs ...int64) bool { + if len(blockerIDs) == 0 { + return false + } + + cond := builder.Eq{"user_blocking.blockee_id": blockeeID}. And(builder.In("user_blocking.blocker_id", blockerIDs)) has, _ := db.GetEngine(ctx).Where(cond).Exist(&Blocking{}) diff --git a/models/user/error.go b/models/user/error.go index a0dc1f9172b..21d50ec8040 100644 --- a/models/user/error.go +++ b/models/user/error.go @@ -31,8 +31,9 @@ func (err ErrUserAlreadyExist) Unwrap() error { // ErrUserNotExist represents a "UserNotExist" kind of error. type ErrUserNotExist struct { - UID int64 - Name string + UID int64 + Name string + ExtraMsg string } // IsErrUserNotExist checks if an error is a ErrUserNotExist. @@ -42,7 +43,11 @@ func IsErrUserNotExist(err error) bool { } func (err ErrUserNotExist) Error() string { - return fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name) + ret := fmt.Sprintf("user does not exist [uid: %d, name: %s]", err.UID, err.Name) + if err.ExtraMsg != "" { + ret += ": " + err.ExtraMsg + } + return ret } // Unwrap unwraps this error as a ErrNotExist error diff --git a/modules/git/fastimport.go b/modules/git/fastimport.go index 048bd4a3e56..6bf0c5e32e9 100644 --- a/modules/git/fastimport.go +++ b/modules/git/fastimport.go @@ -29,6 +29,8 @@ type FastImportCommit struct { Ref string Message string Files []FastImportFile + + Author, Committer *Signature } // ForceFastImportWithInit is for mainly for testing purpose @@ -48,15 +50,32 @@ func ForceFastImportWithInit(ctx context.Context, repoLocalPath string, commits // ForceFastImport is for mainly for testing purpose func ForceFastImport(ctx context.Context, repo RepositoryFacade, commits []FastImportCommit) error { - var buf bytes.Buffer + buf := &bytes.Buffer{} for i, c := range commits { - msg := util.IfZero(c.Message, fmt.Sprintf("commit %d", i+1)) - _, _ = fmt.Fprintf(&buf, "reset %s\n", c.Ref) - _, _ = fmt.Fprintf(&buf, "commit %s\nmark :%d\ncommitter Gitea 1500000000 +0000\n", c.Ref, i+1) - _, _ = fmt.Fprintf(&buf, "data %d\n%s\n", len(msg), msg) + _, _ = fmt.Fprintf(buf, "reset %s\n", c.Ref) + _, _ = fmt.Fprintf(buf, "commit %s\n", c.Ref) + _, _ = fmt.Fprintf(buf, "mark :%d\n", i+1) + + if c.Author != nil { + buf.WriteString("author ") + _ = c.Author.Encode(buf) + buf.WriteByte('\n') + } + if c.Committer != nil { + buf.WriteString("committer ") + _ = c.Committer.Encode(buf) + buf.WriteByte('\n') + } else { + // "committer" is required, so we use a default one if not provided + buf.WriteString("committer Gitea 1500000000 +0000\n") + } + + msg := util.IfZero(c.Message, fmt.Sprintf("test commit %d", i+1)) + _, _ = fmt.Fprintf(buf, "data %d\n%s\n", len(msg), msg) + for _, f := range c.Files { mode := util.IfZero(f.Mode, EntryModeBlob) - _, _ = fmt.Fprintf(&buf, "M %s inline %s\ndata %d\n%s\n", mode.String(), f.Path, len(f.Content), f.Content) + _, _ = fmt.Fprintf(buf, "M %s inline %s\ndata %d\n%s\n", mode.String(), f.Path, len(f.Content), f.Content) } } buf.WriteString("done\n") diff --git a/modules/git/signature_nogogit.go b/modules/git/signature_nogogit.go index d4ddfb23ce8..7a61d8d7eb0 100644 --- a/modules/git/signature_nogogit.go +++ b/modules/git/signature_nogogit.go @@ -8,6 +8,7 @@ package git import ( "fmt" + "io" "time" "gitea.dev/modules/util" @@ -24,7 +25,13 @@ func (s *Signature) String() string { return fmt.Sprintf("%s <%s>", s.Name, s.Email) } -// Decode decodes a byte array representing a signature to signature +// Encode writes the signature for git commit object (same as gogit's object.Signature Encode method) +func (s *Signature) Encode(w io.Writer) error { + _, err := fmt.Fprintf(w, "%s <%s> %d %s", s.Name, s.Email, max(0, s.When.Unix()), s.When.Format("-0700")) + return err +} + +// Decode parses the signature for git commit object (same as gogit's object.Signature Decode method) func (s *Signature) Decode(b []byte) { *s = *parseSignatureFromCommitLine(util.UnsafeBytesToString(b)) } diff --git a/modules/setting/server.go b/modules/setting/server.go index cb91a900e24..4cc6b14f962 100644 --- a/modules/setting/server.go +++ b/modules/setting/server.go @@ -13,6 +13,7 @@ import ( "time" "gitea.dev/modules/log" + "gitea.dev/modules/util" ) // Scheme describes protocol types @@ -274,9 +275,7 @@ func loadServerFrom(rootCfg ConfigProvider) { RedirectOtherPort = sec.Key("REDIRECT_OTHER_PORT").MustBool(false) PortToRedirect = sec.Key("PORT_TO_REDIRECT").MustString("80") RedirectorUseProxyProtocol = sec.Key("REDIRECTOR_USE_PROXY_PROTOCOL").MustBool(UseProxyProtocol) - if len(StaticRootPath) == 0 { - StaticRootPath = AppWorkPath - } + StaticRootPath = util.IfZero(StaticRootPath, AppWorkPath) 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(filepath.Join(AppWorkPath, "data")) diff --git a/modules/test/utils.go b/modules/test/utils.go index 514a9a1141b..fc1211c1e97 100644 --- a/modules/test/utils.go +++ b/modules/test/utils.go @@ -64,7 +64,7 @@ func ParseJSONRedirect(buf []byte) (ret struct { } func IsNormalPageCompleted(s string) bool { - return strings.Contains(s, `