Merge branch 'master' of https://github.com/go-gitea/gitea
# Conflicts: # models/migrations/v51.go
This commit is contained in:
commit
172b1f054a
23
.drone.yml
23
.drone.yml
|
|
@ -55,6 +55,16 @@ pipeline:
|
|||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
build-without-gcc:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
environment:
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- go build -o gitea_no_gcc # test if build succeeds without the sqlite tag
|
||||
when:
|
||||
event: [ push, tag, pull_request ]
|
||||
|
||||
build:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
|
|
@ -86,6 +96,19 @@ pipeline:
|
|||
event: [ push, pull_request ]
|
||||
branch: [ master ]
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
group: test
|
||||
environment:
|
||||
TAGS: bindata sqlite
|
||||
GOPATH: /srv/app
|
||||
commands:
|
||||
- make test
|
||||
when:
|
||||
event: [ push, pull_request ]
|
||||
branch: [ release/* ]
|
||||
|
||||
test:
|
||||
image: webhippie/golang:edge
|
||||
pull: true
|
||||
|
|
|
|||
237
CHANGELOG.md
237
CHANGELOG.md
|
|
@ -1,5 +1,242 @@
|
|||
# Changelog
|
||||
|
||||
## [1.3.1](https://github.com/go-gitea/gitea/releases/tag/v1.3.1) - 2017-12-08
|
||||
* BUGFIXES
|
||||
* Sanitize logs for mirror sync (#3057, #3082) (#3078)
|
||||
* Fix missing branch in release bug (#3108) (#3117)
|
||||
* Fix repo indexer and submodule bug (#3107) (#3110)
|
||||
* Fix legacy URL redirects (#3100) (#3106)
|
||||
* Fix redis session failed (#3086) (#3089)
|
||||
* Fix issue list branch link broken (#3061) (#3070)
|
||||
* Fix missing password length check when change password (#3039) (#3071)
|
||||
|
||||
## [1.3.0](https://github.com/go-gitea/gitea/releases/tag/v1.3.0) - 2017-11-29
|
||||
* BREAKING
|
||||
* Make URL scheme unambiguous (#2408)
|
||||
* FEATURE
|
||||
* Add branch overiew page (#2108)
|
||||
* Code/repo search (#2582)
|
||||
* Add Activity page to repository (#2674)
|
||||
* Issue Timetracking (#2211)
|
||||
* Add orgmode document type on file view and readme (#2525)
|
||||
* Add external markup render support (#2570)
|
||||
* Implementation of discord webhook (#2402)
|
||||
* Webhooks for repo creation/deletion (#1663)
|
||||
* Complete push webhooks (#2530)
|
||||
* Add possibility to record branch information in an issue (#780)
|
||||
* Create new branch from branch selection dropdown (#2130)
|
||||
* Implementation of all repositories of a user from user->settings (#1740)
|
||||
* Add LFS object verification step after upload (#2868)
|
||||
* Configurable SSH cipher suite (#913)
|
||||
* Disable custom Git Hooks globally via configuration file (#2450)
|
||||
* Sync releases table with tags on push and for mirrors (#2459)
|
||||
* BUGFIXES
|
||||
* Fix label comments for French locale (#3017)
|
||||
* Remove duplicate "Max Diff Lines" from config view (#3001)
|
||||
* Fix over-escaped characters (#2992)
|
||||
* Fix go-get, src and raw urls to new scheme (#2986)
|
||||
* Fix error when add user has full name to team (#2975)
|
||||
* Fix files/commits of merged PRs (#2970)
|
||||
* Update golang x/crypto dependencies - Fix SSH transport fail (#2951)
|
||||
* Fix memcache support when value is returned as string always (#2950)
|
||||
* Fix issue link rendering in commit messages (#2897)
|
||||
* Fix adding a new authentication source after selecting OAuth (#2889)
|
||||
* Fix new branch creation to new url scheme (#2884)
|
||||
* Allow spaces in username for LDAP users (#2880)
|
||||
* Fix LFS not returning correct content length when requesting a range … (#2864)
|
||||
* Fix fork repository cycle to self (#2860)
|
||||
* Fix click create pull request button 404 (#2859)
|
||||
* Fix API raw file content access for default branch (#2849)
|
||||
* Clean repository ROOT directory name with filepath.Clean (#2846)
|
||||
* Fix API raw requests for commits and tags (#2841)
|
||||
* Fix order of comments (#2835)
|
||||
* Issue content should not be updated when closing with comment (#2833)
|
||||
* Fix ordering in app.ini and fix run mode option (#2829)
|
||||
* Fix redirect url of legacy commits route (#2825)
|
||||
* Fix commits page url (#2823)
|
||||
* Fix wrong translations (#2818)
|
||||
* Fix dropdown menu position when explore repos (#2808)
|
||||
* Fix Git LFS object/repo link storage in database and small refactoring (#2803)
|
||||
* Use relative URLs for avatars on the dashboard (#2800)
|
||||
* Add checks for commits with missing author and time (#2771)
|
||||
* Fix emojify image URL (#2769)
|
||||
* Hide unactive on explore users and some refactors (#2741)
|
||||
* Fix IE unsupported javascript construction in branch dropdown (#2736)
|
||||
* Only update mirror last update after successful sync (#2730)
|
||||
* Fix semantic-ui style conflict with v-cloak (#2722)
|
||||
* Fixing wrong translation on sort type oldest/latest (#2720)
|
||||
* Fix PR, milestone and label functionality if issue unit is disabled (#2710)
|
||||
* Fix plain readme didn't render correctly on repo home page (#2705)
|
||||
* Fix organization removal from watch table migration (#2703)
|
||||
* Fix repository search function (#2689)
|
||||
* fix panic on gogs webhook creation (#2675)
|
||||
* Fix orgnization user watch repository (#2670)
|
||||
* GPG key email verification no longer case sensitive (#2661) (#2663)
|
||||
* Fix index column deletion (#2651)
|
||||
* table `pull_request` wasn't updated correctly (#2649)
|
||||
* Fix go get response if only app URL is custom in configuration (#2634)
|
||||
* Fix doubled issue tab introduced in migration v16 (#2611)
|
||||
* Rewrite migrations to not depend on future code changes (#2604)
|
||||
* Fix implementation of repo Home func (#2601)
|
||||
* Fix translation upload to crowdin (#2599)
|
||||
* Reduce usage of allcols on update (#2596)
|
||||
* fix go get subpackage bug (#2584)
|
||||
* Fix broken migration to add can_push field back to table (#2574)
|
||||
* fix readme view bug (#2566)
|
||||
* Fix sending mail with a non-latin display name. #2102 (#2559)
|
||||
* Restricting access to fork functioanlity to users with Code access (#2534)
|
||||
* fix updated update on public key (#2514)
|
||||
* Added bucket name to s3 drone plugin (#2505)
|
||||
* fixes 500 error on dashboard when using MSSQL (#2504)
|
||||
* fix wrong rendering of commit detail page (#2503)
|
||||
* Hotfix: Add time manually adds time in nanoseconds (#2499)
|
||||
* Remove repository mirrors from "collaborative" list (#2497)
|
||||
* fix release failed since the wrong token name (#2496)
|
||||
* Fix slice out of bounds error in mailer (#2479)
|
||||
* Fix #2470 (#2477)
|
||||
* fix orgnization webhooks (#2422)
|
||||
* fix webhook test (#2415)
|
||||
* fix missing orgnization discord webhook (#2414)
|
||||
* Fix route handler order (#2409)
|
||||
* Prevent sending emails and notifications to inactive users (#2384)
|
||||
* Move themes to plugin directory. Fixes #2372 (#2375)
|
||||
* fix duplicated feed (#2370)
|
||||
* Fix missing collabrative repos (#2367)
|
||||
* Only check at least one email gpg key (#2266)
|
||||
* don't check minimum key size when disabled (#1754)
|
||||
* Fix run command race (#1470)
|
||||
* fix .netrc authentication (#2700)
|
||||
* Fix so that user can still fork his own repository to his organizations (#2699)
|
||||
* Fix can_push value to false in protected_branch (#2560)
|
||||
* Fix copy in email templates (#2801)
|
||||
* Fix inconsistencies in user settings UI (#2901)
|
||||
* Fix attachments icon size on zoom in/out (#2853)
|
||||
* Fix ignored errors in API route (#2850)
|
||||
* Fix activity css conflit with semantic ui (#2758)
|
||||
* Fix notifications tabs according to semantic-ui docs (#2733)
|
||||
* Fix typos in app.ini (#2732)
|
||||
* Fix duplicated rel attribute (#2549)
|
||||
* Fix tests code to prevent some runtime errors (#2381)
|
||||
* ENHANCEMENT
|
||||
* Memory usage improvements and lower minimal git requirement to 1.7.2 (#3013) (#3028)
|
||||
* Set OpenID support on by default when installing new instance (#3010) (#3027)
|
||||
* Use api.TrackedTime in API (#2807)
|
||||
* Configurable SSH key exchange algorithm and MAC suite (#2806)
|
||||
* Add Safari pinned tab icon (#2799)
|
||||
* Improve force push detect when push (#2798)
|
||||
* Add wrapping to long diff lines (#2789)
|
||||
* Link members and repositories count to each page on org home. (#2787)
|
||||
* Show Sendmail settings on admin config page (#2782)
|
||||
* Add commit count caching (#2774)
|
||||
* Use identicon image for default gravatar. (#2767)
|
||||
* Add default ssh ciphers (#2761)
|
||||
* Remove manual of unsupported option (#2757)
|
||||
* Add search mode option to /api/repo/search (#2756)
|
||||
* Move swagger-ui under /api/v1 (#2746)
|
||||
* Add support for extra sendmail arguments (#2731)
|
||||
* Use buffersize to reduce database connection when iterate (#2724)
|
||||
* Render plain text README.txt monospaced (#2721)
|
||||
* Integration test for activity page (#2704)
|
||||
* Merge password and 2fa page on user settings (#2695)
|
||||
* Allow custom SSH user in UI for built-in SSH server (#2617) (#2678)
|
||||
* Refactor duplicated code in repo handlers (#2657)
|
||||
* Replace deprecated Id method with ID (#2655)
|
||||
* Remove redudant functions and code (#2652)
|
||||
* hide navbar when only 1 sign-in method is available (#2444) (#2648)
|
||||
* Change default sort order (#2647)
|
||||
* Change pull description text (#2075) (#2646)
|
||||
* Remove direct user adding to organization members (#2641)
|
||||
* Use session when creating user (#2638)
|
||||
* Use Semantic UI's Search component for user and repo search (#2636)
|
||||
* Use AfterLoad instead of AfterSet on Structs (#2628)
|
||||
* Remove redudant CheckUnit calls in router (#2627)
|
||||
* Remove repo unit index (#2621)
|
||||
* Remove redudant issue LoadAttributes() calls (#2614)
|
||||
* Make indexer code more reusable (#2590)
|
||||
* Use custom type and constants to hold available order by options (#2572)
|
||||
* Use named ActionType constants in template helper (#2545)
|
||||
* Make basic functionality work without JavaScript (#2541)
|
||||
* Ctrl + Enter to submit forms (#2540)
|
||||
* Automatically regenerate indexer for incompatible versions (#2524)
|
||||
* Set default lfs content path to data/lfs (#2521)
|
||||
* Convert spaces to tabs in footer.tmpl (#2520)
|
||||
* Sort repository tree entries in natural way (#2506)
|
||||
* Open external wiki in new window (#2489)
|
||||
* Use created & updated instead BeforeInsert & BeforeUpdate (#2482)
|
||||
* Hide branch on pull request view or create UI (#2454)
|
||||
* improve protected branch to add whitelist support (#2451)
|
||||
* some refactors for issue and comments (#2419)
|
||||
* Restructure markup & markdown to prepare for multiple markup language… (#2411)
|
||||
* Improve issue search (#2387)
|
||||
* Add UseCompatSSHURI setting (#2356)
|
||||
* Use custom search for each filter type in dashboard (#2343)
|
||||
* Failed authentication are now properly logged (#2334)
|
||||
* Add environment variable support for Docker image (#2201)
|
||||
* Set session and indexers' data files rel to AppDataPath (#2192)
|
||||
* Display commit status on landing page of repo (#1784)
|
||||
* TESTING
|
||||
* Add integration test for logging out (#2892)
|
||||
* Integration test for user deleting account (#2891)
|
||||
* Use different directories for session files in integration tests (#2834)
|
||||
* Add deleted_branch table fixture (#2832)
|
||||
* Include HTTP method in test error message (#2815)
|
||||
* Add repository search unit and integration tests (#2575)
|
||||
* Expand fixtures (#2571)
|
||||
* Fix /api/repo/search integration tests (#2550)
|
||||
* Make integration tests more user-friendly (#2536)
|
||||
* Fix unit test race condition (#2516)
|
||||
* Add missing fixture to clean gpg_key table (#2494)
|
||||
* Hotfix for integration testing (#2473)
|
||||
* Make repo private to not interfere with other tests (#2467)
|
||||
* Error message for integration test (#2410)
|
||||
* Fix "index out of range" runtime error in repo_list tests (#2376)
|
||||
* Add git clone test on integration test (#1682)
|
||||
* TRANSLATION
|
||||
* Fix localization texts that contain semicolon (#2900)
|
||||
* Fix activity locale (#2709)
|
||||
* Update translation from crowdin (#2368)
|
||||
* BUILD
|
||||
* change the email and name to GitBot account. (#2848)
|
||||
* Fix removing backslash before quotes in translations (#2831)
|
||||
* add gitea remote in drone. (#2817)
|
||||
* add remote name for git push. (#2816)
|
||||
* Launch Gitea with custom UID/GID for 'git' user (fixes #2286) (#2791)
|
||||
* Download and pushing translations (#2727)
|
||||
* Automatic update of translations (#2585)
|
||||
* Add pre-build step for nodejs stuff (#2581)
|
||||
* Compress css with nodejs (#2580)
|
||||
* Remove go version check for make fmt (#2558)
|
||||
* Fix lint errors (#2547)
|
||||
* Always run fmt check in CI (#2546)
|
||||
* Fix fmt errors (#2544)
|
||||
* add codecov.io service. (#2493)
|
||||
* Fix some tests : make coverage -> test (#2492)
|
||||
* Fix fmt error in mailer (#2490)
|
||||
* Allow changing integration test database connection using env variables (#2484)
|
||||
* Add changelog config file for generate changelog (#2461)
|
||||
* Changes for latest DroneCI (#2362)
|
||||
* Use standard lessc and minify CSS using Node.js (#2337)
|
||||
* DOCS
|
||||
* Update screenshots on README (#2910)
|
||||
* Gogs -> Gitea (#2909)
|
||||
* Update swagger documentation (#2899)
|
||||
* Fix typo (#2810)
|
||||
* Fix Polish language name spelling (#2766)
|
||||
* Fix Various Grammar Issues and Adjust Unnatural Wording (#2737)
|
||||
* Add maintainer label for docker file (#2658)
|
||||
* Link to gitea-specific Vagrant example (#2624)
|
||||
* add release notes of v1.1.4 (#2463)
|
||||
* Wrap most paragraphs to 80 columns (#2396)
|
||||
* Update CONTRIBUTING following #2329 discussion (#2394)
|
||||
* Update hard-coded version to 1.3.0+dev (#2390)
|
||||
* Clarify Translation Process. Also fix branch names (#2378)
|
||||
* Admin grammar fixes and improvements (#2056)
|
||||
* MISC
|
||||
* Sync MaxGitDiffLineCharacters with conf/app.ini (#2779)
|
||||
* Dockerfile: Updated alpine image to 3.6. (#2486)
|
||||
* Basic VSCode configuration for building and debugging (#2483)
|
||||
* Added vendor dir for js/css libs; Documented sources (#1484) (#2241)
|
||||
|
||||
## [1.2.3](https://github.com/go-gitea/gitea/releases/tag/v1.2.3) - 2017-11-03
|
||||
* BUGFIXES
|
||||
* Only require one email when validating GPG key (#2266, #2467, #2663) (#2788)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM alpine:3.6
|
||||
FROM alpine:3.7
|
||||
LABEL maintainer="The Gitea Authors"
|
||||
|
||||
EXPOSE 22 3000
|
||||
|
|
|
|||
4
Makefile
4
Makefile
|
|
@ -131,7 +131,7 @@ fmt-check:
|
|||
|
||||
.PHONY: test
|
||||
test:
|
||||
$(GO) test $(PACKAGES)
|
||||
$(GO) test -tags=sqlite $(PACKAGES)
|
||||
|
||||
.PHONY: coverage
|
||||
coverage:
|
||||
|
|
@ -142,7 +142,7 @@ coverage:
|
|||
|
||||
.PHONY: unit-test-coverage
|
||||
unit-test-coverage:
|
||||
for PKG in $(PACKAGES); do $(GO) test -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
for PKG in $(PACKAGES); do $(GO) test -tags=sqlite -cover -coverprofile $$GOPATH/src/$$PKG/coverage.out $$PKG || exit 1; done;
|
||||
|
||||
.PHONY: test-vendor
|
||||
test-vendor:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/private"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/dgrijalva/jwt-go"
|
||||
|
|
@ -219,8 +220,8 @@ func runServ(c *cli.Context) error {
|
|||
fail("Internal error", "GetDeployKey: %v", err)
|
||||
}
|
||||
|
||||
deployKey.Updated = time.Now()
|
||||
if err = models.UpdateDeployKey(deployKey); err != nil {
|
||||
deployKey.UpdatedUnix = util.TimeStampNow()
|
||||
if err = models.UpdateDeployKeyCols(deployKey, "updated_unix"); err != nil {
|
||||
fail("Internal error", "UpdateDeployKey: %v", err)
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
30
cmd/web.go
30
cmd/web.go
|
|
@ -19,8 +19,10 @@ import (
|
|||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
context2 "github.com/gorilla/context"
|
||||
"github.com/urfave/cli"
|
||||
ini "gopkg.in/ini.v1"
|
||||
)
|
||||
|
||||
// CmdWeb represents the available web sub-command.
|
||||
|
|
@ -69,6 +71,34 @@ func runWeb(ctx *cli.Context) error {
|
|||
if ctx.IsSet("port") {
|
||||
setting.AppURL = strings.Replace(setting.AppURL, setting.HTTPPort, ctx.String("port"), 1)
|
||||
setting.HTTPPort = ctx.String("port")
|
||||
|
||||
switch setting.Protocol {
|
||||
case setting.UnixSocket:
|
||||
case setting.FCGI:
|
||||
default:
|
||||
// Save LOCAL_ROOT_URL if port changed
|
||||
cfg := ini.Empty()
|
||||
if com.IsFile(setting.CustomConf) {
|
||||
// Keeps custom settings if there is already something.
|
||||
if err := cfg.Append(setting.CustomConf); err != nil {
|
||||
return fmt.Errorf("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||
}
|
||||
}
|
||||
|
||||
defaultLocalURL := string(setting.Protocol) + "://"
|
||||
if setting.HTTPAddr == "0.0.0.0" {
|
||||
defaultLocalURL += "localhost"
|
||||
} else {
|
||||
defaultLocalURL += setting.HTTPAddr
|
||||
}
|
||||
defaultLocalURL += ":" + setting.HTTPPort + "/"
|
||||
|
||||
cfg.Section("server").Key("LOCAL_ROOT_URL").SetValue(defaultLocalURL)
|
||||
|
||||
if err := cfg.SaveTo(setting.CustomConf); err != nil {
|
||||
return fmt.Errorf("Error saving generated JWT Secret to custom config: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var listenAddr string
|
||||
|
|
|
|||
|
|
@ -175,14 +175,14 @@ LFS_START_SERVER = false
|
|||
; Where your lfs files put on, default is data/lfs.
|
||||
LFS_CONTENT_PATH = data/lfs
|
||||
; LFS authentication secret, changed this to yourself.
|
||||
LFS_JWT_SECRET =
|
||||
LFS_JWT_SECRET =
|
||||
|
||||
; Define allowed algorithms and their minimum key length (use -1 to disable a type)
|
||||
[ssh.minimum_key_sizes]
|
||||
ED25519 = 256
|
||||
ECDSA = 256
|
||||
RSA = 2048
|
||||
DSA = 1024
|
||||
ECDSA = 256
|
||||
RSA = 2048
|
||||
DSA = 1024
|
||||
|
||||
[database]
|
||||
; Either "mysql", "postgres", "mssql" or "sqlite3", it's your choice
|
||||
|
|
@ -496,7 +496,11 @@ SCHEDULE = @every 24h
|
|||
|
||||
; Clean up old repository archives
|
||||
[cron.archive_cleanup]
|
||||
; Whether to enable the job
|
||||
ENABLED = true
|
||||
; Whether to always run at least once at start up time (if ENABLED)
|
||||
RUN_AT_START = true
|
||||
; Time interval for job to run
|
||||
SCHEDULE = @every 24h
|
||||
; Archives created more than OLDER_THAN ago are subject to deletion
|
||||
OLDER_THAN = 24h
|
||||
|
|
|
|||
|
|
@ -41,6 +41,10 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
|||
- `FORCE_PRIVATE`: Force every new repository to be private.
|
||||
- `MAX_CREATION_LIMIT`: Global maximum creation limit of repositories per user, `-1` means no limit.
|
||||
- `PULL_REQUEST_QUEUE_LENGTH`:exclamation:: Length of pull request patch test queue, make it as large as possible.
|
||||
- `MIRROR_QUEUE_LENGTH`: Patch test queue length, increase if pull request patch testing starts hanging. Defaults to 1000.
|
||||
- `PREFERRED_LICENSES`: Preferred Licenses to place at the top of the List. Name must match file name in conf/license or custom/conf/license. Defaults to 'Apache License 2.0,MIT License'
|
||||
- `DISABLE_HTTP_GIT`: Disable ability to interact with repositories by HTTP protocol. Defaults to false
|
||||
- `USE_COMPAT_SSH_URI`: Force ssh:// clone url instead of scp-style uri when default SSH port is used. Defaults to false.
|
||||
|
||||
## UI (`ui`)
|
||||
|
||||
|
|
@ -189,6 +193,13 @@ Note: Actually, Gitea supports only SMTP with STARTTLS.
|
|||
- `ENABLED`: Enable this to run cron tasks periodically.
|
||||
- `RUN_AT_START`: Enable this to run cron tasks at start time.
|
||||
|
||||
### Cron - Cleanup old repository archives (`cron.archive_cleanup`)
|
||||
|
||||
- `ENABLED`: Enable service. Defaults to true.
|
||||
- `RUN_AT_START`: Run tasks at start up time (if ENABLED). Defaults to true.
|
||||
- `SCHEDULE`: Cron syntax for scheduling repository archive cleanup, e.g. `@every 1h`. Defaults to `@every 24h`.
|
||||
- `OLDER_THAN`: Archives created more than `OLDER_THAN` ago are subject to deletion, e.g. `12h`. Defaults to `24h`.
|
||||
|
||||
### Cron - Update Mirrors (`cron.update_mirrors`)
|
||||
|
||||
- `SCHEDULE`: Cron syntax for scheduling update mirrors, e.g. `@every 1h`.
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ func TestAPILFSLocksLogged(t *testing.T) {
|
|||
assert.Len(t, lfsLocks.Locks, test.totalCount)
|
||||
for i, lock := range lfsLocks.Locks {
|
||||
assert.EqualValues(t, test.locksOwners[i].DisplayName(), lock.Owner.Name)
|
||||
assert.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 1*time.Second)
|
||||
assert.WithinDuration(t, test.locksTimes[i], lock.LockedAt, 3*time.Second)
|
||||
}
|
||||
|
||||
req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/%s.git/info/lfs/locks/verify", test.repo.FullName()), map[string]string{})
|
||||
|
|
|
|||
|
|
@ -6,27 +6,32 @@ package integrations
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func onGiteaWebRun(t *testing.T, callback func(*testing.T, string)) {
|
||||
func onGiteaWebRun(t *testing.T, callback func(*testing.T, *url.URL)) {
|
||||
s := http.Server{
|
||||
Handler: mac,
|
||||
}
|
||||
|
||||
listener, err := net.Listen("tcp", "")
|
||||
u, err := url.Parse(setting.AppURL)
|
||||
assert.NoError(t, err)
|
||||
listener, err := net.Listen("tcp", u.Host)
|
||||
assert.NoError(t, err)
|
||||
|
||||
defer func() {
|
||||
|
|
@ -37,24 +42,144 @@ func onGiteaWebRun(t *testing.T, callback func(*testing.T, string)) {
|
|||
|
||||
go s.Serve(listener)
|
||||
|
||||
_, port, err := net.SplitHostPort(listener.Addr().String())
|
||||
assert.NoError(t, err)
|
||||
|
||||
callback(t, fmt.Sprintf("http://localhost:%s/", port))
|
||||
callback(t, u)
|
||||
}
|
||||
|
||||
func TestClone_ViaHTTP_NoLogin(t *testing.T) {
|
||||
func TestGit(t *testing.T) {
|
||||
prepareTestEnv(t)
|
||||
|
||||
onGiteaWebRun(t, func(t *testing.T, urlPrefix string) {
|
||||
dstPath, err := ioutil.TempDir("", "repo1")
|
||||
onGiteaWebRun(t, func(t *testing.T, u *url.URL) {
|
||||
dstPath, err := ioutil.TempDir("", "repo-tmp-17")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstPath)
|
||||
u.Path = "user2/repo1.git"
|
||||
|
||||
err = git.Clone(fmt.Sprintf("%suser2/repo1.git", urlPrefix),
|
||||
dstPath, git.CloneRepoOptions{})
|
||||
assert.NoError(t, err)
|
||||
t.Run("Standard", func(t *testing.T) {
|
||||
|
||||
assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
|
||||
t.Run("CloneNoLogin", func(t *testing.T) {
|
||||
dstLocalPath, err := ioutil.TempDir("", "repo1")
|
||||
assert.NoError(t, err)
|
||||
defer os.RemoveAll(dstLocalPath)
|
||||
err = git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
|
||||
})
|
||||
|
||||
t.Run("CreateRepo", func(t *testing.T) {
|
||||
session := loginUser(t, "user2")
|
||||
req := NewRequestWithJSON(t, "POST", "/api/v1/user/repos", &api.CreateRepoOption{
|
||||
AutoInit: true,
|
||||
Description: "Temporary repo",
|
||||
Name: "repo-tmp-17",
|
||||
Private: false,
|
||||
Gitignores: "",
|
||||
License: "WTFPL",
|
||||
Readme: "Default",
|
||||
})
|
||||
session.MakeRequest(t, req, http.StatusCreated)
|
||||
})
|
||||
|
||||
u.Path = "user2/repo-tmp-17.git"
|
||||
u.User = url.UserPassword("user2", userPassword)
|
||||
t.Run("Clone", func(t *testing.T) {
|
||||
err = git.Clone(u.String(), dstPath, git.CloneRepoOptions{})
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, com.IsExist(filepath.Join(dstPath, "README.md")))
|
||||
})
|
||||
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
data := make([]byte, 1024)
|
||||
_, err := rand.Read(data)
|
||||
assert.NoError(t, err)
|
||||
tmpFile, err := ioutil.TempFile(dstPath, "data-file-")
|
||||
defer tmpFile.Close()
|
||||
_, err = tmpFile.Write(data)
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Commit
|
||||
err = git.AddChanges(dstPath, false, filepath.Base(tmpFile.Name()))
|
||||
assert.NoError(t, err)
|
||||
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "User Two",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "User Two",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Testing commit",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Push
|
||||
err = git.Push(dstPath, git.PushOptions{
|
||||
Branch: "master",
|
||||
Remote: u.String(),
|
||||
Force: false,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
})
|
||||
t.Run("LFS", func(t *testing.T) {
|
||||
t.Run("PushCommit", func(t *testing.T) {
|
||||
/* Generate random file */
|
||||
data := make([]byte, 1024)
|
||||
_, err := rand.Read(data)
|
||||
assert.NoError(t, err)
|
||||
tmpFile, err := ioutil.TempFile(dstPath, "data-file-")
|
||||
defer tmpFile.Close()
|
||||
_, err = tmpFile.Write(data)
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Setup git LFS
|
||||
_, err = git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("track", "data-file-*").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Commit
|
||||
err = git.AddChanges(dstPath, false, ".gitattributes", filepath.Base(tmpFile.Name()))
|
||||
assert.NoError(t, err)
|
||||
err = git.CommitChanges(dstPath, git.CommitChangesOptions{
|
||||
Committer: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "User Two",
|
||||
When: time.Now(),
|
||||
},
|
||||
Author: &git.Signature{
|
||||
Email: "user2@example.com",
|
||||
Name: "User Two",
|
||||
When: time.Now(),
|
||||
},
|
||||
Message: "Testing LFS ",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
//Push
|
||||
u.User = url.UserPassword("user2", userPassword)
|
||||
err = git.Push(dstPath, git.PushOptions{
|
||||
Branch: "master",
|
||||
Remote: u.String(),
|
||||
Force: false,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Locks", func(t *testing.T) {
|
||||
_, err = git.NewCommand("remote").AddArguments("set-url", "origin", u.String()).RunInDir(dstPath) //TODO add test ssh git-lfs-creds
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("lock", "README.md").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
_, err = git.NewCommand("lfs").AddArguments("unlock", "README.md").RunInDir(dstPath)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
})
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' post-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' pre-receive
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
#!/usr/bin/env bash
|
||||
"$GITEA_ROOT/gitea" hook --config='integrations/app.ini' update $1 $2 $3
|
||||
"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"code.gitea.io/gitea/routers"
|
||||
"code.gitea.io/gitea/routers/routes"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/macaron.v1"
|
||||
|
|
@ -136,6 +137,7 @@ func initIntegrationTest() {
|
|||
func prepareTestEnv(t testing.TB) {
|
||||
assert.NoError(t, models.LoadFixtures())
|
||||
assert.NoError(t, os.RemoveAll(setting.RepoRootPath))
|
||||
assert.NoError(t, os.RemoveAll(models.LocalCopyPath()))
|
||||
|
||||
assert.NoError(t, com.CopyDir(path.Join(filepath.Dir(setting.AppPath), "integrations/gitea-repositories-meta"),
|
||||
setting.RepoRootPath))
|
||||
|
|
@ -259,12 +261,37 @@ func MakeRequest(t testing.TB, req *http.Request, expectedStatus int) *httptest.
|
|||
recorder := httptest.NewRecorder()
|
||||
mac.ServeHTTP(recorder, req)
|
||||
if expectedStatus != NoExpectedStatus {
|
||||
assert.EqualValues(t, expectedStatus, recorder.Code,
|
||||
"Request: %s %s", req.Method, req.URL.String())
|
||||
if !assert.EqualValues(t, expectedStatus, recorder.Code,
|
||||
"Request: %s %s", req.Method, req.URL.String()) {
|
||||
logUnexpectedResponse(t, recorder)
|
||||
}
|
||||
}
|
||||
return recorder
|
||||
}
|
||||
|
||||
// logUnexpectedResponse logs the contents of an unexpected response.
|
||||
func logUnexpectedResponse(t testing.TB, recorder *httptest.ResponseRecorder) {
|
||||
respBytes := recorder.Body.Bytes()
|
||||
if len(respBytes) == 0 {
|
||||
return
|
||||
} else if len(respBytes) < 500 {
|
||||
// if body is short, just log the whole thing
|
||||
t.Log("Response:", string(respBytes))
|
||||
return
|
||||
}
|
||||
|
||||
// log the "flash" error message, if one exists
|
||||
// we must create a new buffer, so that we don't "use up" resp.Body
|
||||
htmlDoc, err := goquery.NewDocumentFromReader(bytes.NewBuffer(respBytes))
|
||||
if err != nil {
|
||||
return // probably a non-HTML response
|
||||
}
|
||||
errMsg := htmlDoc.Find(".ui.negative.message").Text()
|
||||
if len(errMsg) > 0 {
|
||||
t.Log("A flash error message was found:", errMsg)
|
||||
}
|
||||
}
|
||||
|
||||
func DecodeJSON(t testing.TB, resp *httptest.ResponseRecorder, v interface{}) {
|
||||
decoder := json.NewDecoder(resp.Body)
|
||||
assert.NoError(t, decoder.Decode(v))
|
||||
|
|
@ -276,9 +303,3 @@ func GetCSRF(t testing.TB, session *TestSession, urlStr string) string {
|
|||
doc := NewHTMLParser(t, resp.Body)
|
||||
return doc.GetCSRF()
|
||||
}
|
||||
|
||||
func RedirectURL(t testing.TB, resp *httptest.ResponseRecorder) string {
|
||||
urlSlice := resp.HeaderMap["Location"]
|
||||
assert.NotEmpty(t, urlSlice, "No redirect URL founds")
|
||||
return urlSlice[0]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -122,7 +123,7 @@ func testNewIssue(t *testing.T, session *TestSession, user, repo, title, content
|
|||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
issueURL := RedirectURL(t, resp)
|
||||
issueURL := test.RedirectURL(resp)
|
||||
req = NewRequest(t, "GET", issueURL)
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
|
|
@ -153,7 +154,7 @@ func testIssueAddComment(t *testing.T, session *TestSession, issueURL, content,
|
|||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
req = NewRequest(t, "GET", RedirectURL(t, resp))
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -46,13 +47,15 @@ func TestRedirectsNoLogin(t *testing.T) {
|
|||
prepareTestEnv(t)
|
||||
|
||||
var redirects = map[string]string{
|
||||
"/user2/repo1/commits/master": "/user2/repo1/commits/branch/master",
|
||||
"/user2/repo1/src/master": "/user2/repo1/src/branch/master",
|
||||
"/user2/repo1/commits/master": "/user2/repo1/commits/branch/master",
|
||||
"/user2/repo1/src/master": "/user2/repo1/src/branch/master",
|
||||
"/user2/repo1/src/master/file.txt": "/user2/repo1/src/branch/master/file.txt",
|
||||
"/user2/repo1/src/master/directory/file.txt": "/user2/repo1/src/branch/master/directory/file.txt",
|
||||
}
|
||||
for link, redirectLink := range redirects {
|
||||
req := NewRequest(t, "GET", link)
|
||||
resp := MakeRequest(t, req, http.StatusFound)
|
||||
assert.EqualValues(t, path.Join(setting.AppSubURL, redirectLink), RedirectURL(t, resp))
|
||||
assert.EqualValues(t, path.Join(setting.AppSubURL, redirectLink), test.RedirectURL(resp))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -54,7 +56,7 @@ func TestPullMerge(t *testing.T) {
|
|||
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
|
||||
elem := strings.Split(RedirectURL(t, resp), "/")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
}
|
||||
|
|
@ -67,7 +69,7 @@ func TestPullCleanUpAfterMerge(t *testing.T) {
|
|||
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "feature/test")
|
||||
|
||||
elem := strings.Split(RedirectURL(t, resp), "/")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import (
|
|||
"net/http"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -38,7 +40,7 @@ func createNewRelease(t *testing.T, session *TestSession, repoURL, tag, title st
|
|||
|
||||
resp = session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
RedirectURL(t, resp) // check that redirect URL exists
|
||||
test.RedirectURL(resp) // check that redirect URL exists
|
||||
}
|
||||
|
||||
func checkLatestReleaseAndCount(t *testing.T, session *TestSession, repoURL, version, label string, count int) {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -20,7 +22,7 @@ func TestRepoActivity(t *testing.T) {
|
|||
testRepoFork(t, session, "user2", "repo1", "user1", "repo1")
|
||||
testEditFile(t, session, "user1", "repo1", "master", "README.md", "Hello, World (Edited)\n")
|
||||
resp := testPullCreate(t, session, "user1", "repo1", "master")
|
||||
elem := strings.Split(RedirectURL(t, resp), "/")
|
||||
elem := strings.Split(test.RedirectURL(resp), "/")
|
||||
assert.EqualValues(t, "pulls", elem[3])
|
||||
testPullMerge(t, session, elem[1], elem[2], elem[4])
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import (
|
|||
"strings"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -29,7 +31,7 @@ func testCreateBranch(t *testing.T, session *TestSession, user, repo, oldRefSubU
|
|||
if expectedStatus != http.StatusFound {
|
||||
return ""
|
||||
}
|
||||
return RedirectURL(t, resp)
|
||||
return test.RedirectURL(resp)
|
||||
}
|
||||
|
||||
func TestCreateBranch(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -47,7 +49,7 @@ func testViewTimetrackingControls(t *testing.T, session *TestSession, user, repo
|
|||
if canTrackTime {
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
req = NewRequest(t, "GET", RedirectURL(t, resp))
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||
|
||||
|
|
@ -65,7 +67,7 @@ func testViewTimetrackingControls(t *testing.T, session *TestSession, user, repo
|
|||
})
|
||||
resp = session.MakeRequest(t, req, http.StatusSeeOther)
|
||||
|
||||
req = NewRequest(t, "GET", RedirectURL(t, resp))
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc = NewHTMLParser(t, resp.Body)
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -86,7 +87,7 @@ func TestRenameReservedUsername(t *testing.T) {
|
|||
})
|
||||
resp := session.MakeRequest(t, req, http.StatusFound)
|
||||
|
||||
req = NewRequest(t, "GET", RedirectURL(t, resp))
|
||||
req = NewRequest(t, "GET", test.RedirectURL(resp))
|
||||
resp = session.MakeRequest(t, req, http.StatusOK)
|
||||
htmlDoc := NewHTMLParser(t, resp.Body)
|
||||
assert.Contains(t,
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
|
|
@ -85,15 +86,9 @@ type Action struct {
|
|||
Comment *Comment `xorm:"-"`
|
||||
IsDeleted bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||
RefName string
|
||||
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||
Content string `xorm:"TEXT"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (a *Action) AfterLoad() {
|
||||
a.Created = time.Unix(a.CreatedUnix, 0).Local()
|
||||
IsPrivate bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||
Content string `xorm:"TEXT"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// GetOpType gets the ActionType of this action.
|
||||
|
|
@ -229,7 +224,7 @@ func (a *Action) GetContent() string {
|
|||
|
||||
// GetCreate returns the action creation time.
|
||||
func (a *Action) GetCreate() time.Time {
|
||||
return a.Created
|
||||
return a.CreatedUnix.AsTime()
|
||||
}
|
||||
|
||||
// GetIssueInfos returns a list of issues associated with
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ package models
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
|
@ -26,14 +25,8 @@ const (
|
|||
type Notice struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type NoticeType
|
||||
Description string `xorm:"TEXT"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (n *Notice) AfterLoad() {
|
||||
n.Created = time.Unix(n.CreatedUnix, 0).Local()
|
||||
Description string `xorm:"TEXT"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// TrStr returns a translation format string.
|
||||
|
|
|
|||
|
|
@ -10,11 +10,11 @@ import (
|
|||
"mime/multipart"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
gouuid "github.com/satori/go.uuid"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// Attachment represent a attachment of issue/comment/release.
|
||||
|
|
@ -25,24 +25,14 @@ type Attachment struct {
|
|||
ReleaseID int64 `xorm:"INDEX"`
|
||||
CommentID int64
|
||||
Name string
|
||||
DownloadCount int64 `xorm:"DEFAULT 0"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the value of a field of
|
||||
// this object.
|
||||
func (a *Attachment) AfterLoad() {
|
||||
a.Created = time.Unix(a.CreatedUnix, 0).Local()
|
||||
DownloadCount int64 `xorm:"DEFAULT 0"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
}
|
||||
|
||||
// IncreaseDownloadCount is update download count + 1
|
||||
func (a *Attachment) IncreaseDownloadCount() error {
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
// Update download count.
|
||||
if _, err := sess.Exec("UPDATE `attachment` SET download_count=download_count+1 WHERE id=?", a.ID); err != nil {
|
||||
if _, err := x.Exec("UPDATE `attachment` SET download_count=download_count+1 WHERE id=?", a.ID); err != nil {
|
||||
return fmt.Errorf("increase attachment count: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -29,12 +29,10 @@ type ProtectedBranch struct {
|
|||
BranchName string `xorm:"UNIQUE(s)"`
|
||||
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
||||
EnableWhitelist bool
|
||||
WhitelistUserIDs []int64 `xorm:"JSON TEXT"`
|
||||
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
WhitelistUserIDs []int64 `xorm:"JSON TEXT"`
|
||||
WhitelistTeamIDs []int64 `xorm:"JSON TEXT"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
}
|
||||
|
||||
// IsProtected returns if the branch is protected
|
||||
|
|
@ -197,19 +195,13 @@ func (repo *Repository) DeleteProtectedBranch(id int64) (err error) {
|
|||
|
||||
// DeletedBranch struct
|
||||
type DeletedBranch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Commit string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
DeletedByID int64 `xorm:"INDEX"`
|
||||
DeletedBy *User `xorm:"-"`
|
||||
Deleted time.Time `xorm:"-"`
|
||||
DeletedUnix int64 `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (deletedBranch *DeletedBranch) AfterLoad() {
|
||||
deletedBranch.Deleted = time.Unix(deletedBranch.DeletedUnix, 0).Local()
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Name string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
Commit string `xorm:"UNIQUE(s) NOT NULL"`
|
||||
DeletedByID int64 `xorm:"INDEX"`
|
||||
DeletedBy *User `xorm:"-"`
|
||||
DeletedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// AddDeletedBranch adds a deleted branch to the database
|
||||
|
|
|
|||
|
|
@ -19,3 +19,25 @@
|
|||
issue_id: 2
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
|
||||
-
|
||||
id: 3
|
||||
user_id: 2
|
||||
repo_id: 1
|
||||
status: 3 # pinned
|
||||
source: 1 # issue
|
||||
updated_by: 1
|
||||
issue_id: 2
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
|
||||
-
|
||||
id: 4
|
||||
user_id: 2
|
||||
repo_id: 1
|
||||
status: 1 # unread
|
||||
source: 1 # issue
|
||||
updated_by: 1
|
||||
issue_id: 2
|
||||
created_unix: 946684800
|
||||
updated_unix: 946684800
|
||||
1
models/fixtures/public_key.yml
Normal file
1
models/fixtures/public_key.yml
Normal file
|
|
@ -0,0 +1 @@
|
|||
[] # empty
|
||||
|
|
@ -238,7 +238,7 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
|
|||
var (
|
||||
diff = &Diff{Files: make([]*DiffFile, 0)}
|
||||
|
||||
curFile *DiffFile
|
||||
curFile = &DiffFile{}
|
||||
curSection = &DiffSection{
|
||||
Lines: make([]*DiffLine, 0, 10),
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
"github.com/keybase/go-crypto/openpgp"
|
||||
|
|
@ -26,17 +27,14 @@ import (
|
|||
|
||||
// GPGKey represents a GPG key.
|
||||
type GPGKey struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
KeyID string `xorm:"INDEX CHAR(16) NOT NULL"`
|
||||
PrimaryKeyID string `xorm:"CHAR(16)"`
|
||||
Content string `xorm:"TEXT NOT NULL"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
Expired time.Time `xorm:"-"`
|
||||
ExpiredUnix int64
|
||||
Added time.Time `xorm:"-"`
|
||||
AddedUnix int64
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
KeyID string `xorm:"INDEX CHAR(16) NOT NULL"`
|
||||
PrimaryKeyID string `xorm:"CHAR(16)"`
|
||||
Content string `xorm:"TEXT NOT NULL"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
ExpiredUnix util.TimeStamp
|
||||
AddedUnix util.TimeStamp
|
||||
SubsKey []*GPGKey `xorm:"-"`
|
||||
Emails []*EmailAddress
|
||||
CanSign bool
|
||||
|
|
@ -47,17 +45,11 @@ type GPGKey struct {
|
|||
|
||||
// BeforeInsert will be invoked by XORM before inserting a record
|
||||
func (key *GPGKey) BeforeInsert() {
|
||||
key.AddedUnix = time.Now().Unix()
|
||||
key.ExpiredUnix = key.Expired.Unix()
|
||||
key.CreatedUnix = key.Created.Unix()
|
||||
key.AddedUnix = util.TimeStampNow()
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (key *GPGKey) AfterLoad(session *xorm.Session) {
|
||||
key.Added = time.Unix(key.AddedUnix, 0).Local()
|
||||
key.Expired = time.Unix(key.ExpiredUnix, 0).Local()
|
||||
key.Created = time.Unix(key.CreatedUnix, 0).Local()
|
||||
|
||||
err := session.Where("primary_key_id=?", key.KeyID).Find(&key.SubsKey)
|
||||
if err != nil {
|
||||
log.Error(3, "Find Sub GPGkeys[%d]: %v", key.KeyID, err)
|
||||
|
|
@ -163,8 +155,8 @@ func parseSubGPGKey(ownerID int64, primaryID string, pubkey *packet.PublicKey, e
|
|||
KeyID: pubkey.KeyIdString(),
|
||||
PrimaryKeyID: primaryID,
|
||||
Content: content,
|
||||
Created: pubkey.CreationTime,
|
||||
Expired: expiry,
|
||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()),
|
||||
ExpiredUnix: util.TimeStamp(expiry.Unix()),
|
||||
CanSign: pubkey.CanSign(),
|
||||
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(),
|
||||
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(),
|
||||
|
|
@ -236,8 +228,8 @@ func parseGPGKey(ownerID int64, e *openpgp.Entity) (*GPGKey, error) {
|
|||
KeyID: pubkey.KeyIdString(),
|
||||
PrimaryKeyID: "",
|
||||
Content: content,
|
||||
Created: pubkey.CreationTime,
|
||||
Expired: expiry,
|
||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()),
|
||||
ExpiredUnix: util.TimeStamp(expiry.Unix()),
|
||||
Emails: emails,
|
||||
SubsKey: subkeys,
|
||||
CanSign: pubkey.CanSign(),
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ package models
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
|
@ -109,7 +111,7 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
|
|||
key := &GPGKey{
|
||||
KeyID: pubkey.KeyIdString(),
|
||||
Content: content,
|
||||
Created: pubkey.CreationTime,
|
||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()),
|
||||
CanSign: pubkey.CanSign(),
|
||||
CanEncryptComms: pubkey.PubKeyAlgo.CanEncrypt(),
|
||||
CanEncryptStorage: pubkey.PubKeyAlgo.CanEncrypt(),
|
||||
|
|
@ -119,7 +121,7 @@ MkM/fdpyc2hY7Dl/+qFmN5MG5yGmMpQcX+RNNR222ibNC1D3wg==
|
|||
cannotsignkey := &GPGKey{
|
||||
KeyID: pubkey.KeyIdString(),
|
||||
Content: content,
|
||||
Created: pubkey.CreationTime,
|
||||
CreatedUnix: util.TimeStamp(pubkey.CreationTime.Unix()),
|
||||
CanSign: false,
|
||||
CanEncryptComms: false,
|
||||
CanEncryptStorage: false,
|
||||
|
|
|
|||
|
|
@ -9,7 +9,6 @@ import (
|
|||
"path"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
"github.com/Unknwon/com"
|
||||
|
|
@ -45,31 +44,15 @@ type Issue struct {
|
|||
NumComments int
|
||||
Ref string
|
||||
|
||||
Deadline time.Time `xorm:"-"`
|
||||
DeadlineUnix int64 `xorm:"INDEX"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
DeadlineUnix util.TimeStamp `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
Attachments []*Attachment `xorm:"-"`
|
||||
Comments []*Comment `xorm:"-"`
|
||||
Reactions ReactionList `xorm:"-"`
|
||||
}
|
||||
|
||||
// BeforeUpdate is invoked from XORM before updating this object.
|
||||
func (issue *Issue) BeforeUpdate() {
|
||||
issue.DeadlineUnix = issue.Deadline.Unix()
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the value of a field of
|
||||
// this object.
|
||||
func (issue *Issue) AfterLoad() {
|
||||
issue.Deadline = time.Unix(issue.DeadlineUnix, 0).Local()
|
||||
issue.Created = time.Unix(issue.CreatedUnix, 0).Local()
|
||||
issue.Updated = time.Unix(issue.UpdatedUnix, 0).Local()
|
||||
}
|
||||
|
||||
func (issue *Issue) loadRepo(e Engine) (err error) {
|
||||
if issue.Repo == nil {
|
||||
issue.Repo, err = getRepositoryByID(e, issue.RepoID)
|
||||
|
|
@ -307,8 +290,8 @@ func (issue *Issue) APIFormat() *api.Issue {
|
|||
Labels: apiLabels,
|
||||
State: issue.State(),
|
||||
Comments: issue.NumComments,
|
||||
Created: issue.Created,
|
||||
Updated: issue.Updated,
|
||||
Created: issue.CreatedUnix.AsTime(),
|
||||
Updated: issue.UpdatedUnix.AsTime(),
|
||||
}
|
||||
|
||||
if issue.Milestone != nil {
|
||||
|
|
@ -322,7 +305,7 @@ func (issue *Issue) APIFormat() *api.Issue {
|
|||
HasMerged: issue.PullRequest.HasMerged,
|
||||
}
|
||||
if issue.PullRequest.HasMerged {
|
||||
apiIssue.PullRequest.Merged = &issue.PullRequest.Merged
|
||||
apiIssue.PullRequest.Merged = issue.PullRequest.MergedUnix.AsTimePtr()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -599,7 +582,7 @@ func updateIssueCols(e Engine, issue *Issue, cols ...string) error {
|
|||
if _, err := e.ID(issue.ID).Cols(cols...).Update(issue); err != nil {
|
||||
return err
|
||||
}
|
||||
UpdateIssueIndexer(issue.ID)
|
||||
UpdateIssueIndexerCols(issue.ID, cols...)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ package models
|
|||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/builder"
|
||||
|
|
@ -17,6 +16,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/markup"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// CommentType defines whether a comment is just a simple comment, an action (like close) or a reference.
|
||||
|
|
@ -104,10 +104,8 @@ type Comment struct {
|
|||
Content string `xorm:"TEXT"`
|
||||
RenderedContent string `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
|
||||
// Reference issue in commit message
|
||||
CommitSHA string `xorm:"VARCHAR(40)"`
|
||||
|
|
@ -121,9 +119,6 @@ type Comment struct {
|
|||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (c *Comment) AfterLoad(session *xorm.Session) {
|
||||
c.Created = time.Unix(c.CreatedUnix, 0).Local()
|
||||
c.Updated = time.Unix(c.UpdatedUnix, 0).Local()
|
||||
|
||||
var err error
|
||||
c.Attachments, err = getAttachmentsByCommentID(session, c.ID)
|
||||
if err != nil {
|
||||
|
|
@ -197,8 +192,8 @@ func (c *Comment) APIFormat() *api.Comment {
|
|||
IssueURL: c.IssueURL(),
|
||||
PRURL: c.PRURL(),
|
||||
Body: c.Content,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
Created: c.CreatedUnix.AsTime(),
|
||||
Updated: c.UpdatedUnix.AsTime(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,9 @@ func TestCreateComment(t *testing.T) {
|
|||
assert.EqualValues(t, "Hello", comment.Content)
|
||||
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||
assert.EqualValues(t, doer.ID, comment.PosterID)
|
||||
AssertInt64InRange(t, now, then, comment.CreatedUnix)
|
||||
AssertInt64InRange(t, now, then, int64(comment.CreatedUnix))
|
||||
AssertExistsAndLoadBean(t, comment) // assert actually added to DB
|
||||
|
||||
updatedIssue := AssertExistsAndLoadBean(t, &Issue{ID: issue.ID}).(*Issue)
|
||||
AssertInt64InRange(t, now, then, updatedIssue.UpdatedUnix)
|
||||
AssertInt64InRange(t, now, then, int64(updatedIssue.UpdatedUnix))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -102,6 +102,26 @@ func (issue *Issue) update() indexer.IssueIndexerUpdate {
|
|||
}
|
||||
}
|
||||
|
||||
// updateNeededCols whether a change to the specified columns requires updating
|
||||
// the issue indexer
|
||||
func updateNeededCols(cols []string) bool {
|
||||
for _, col := range cols {
|
||||
switch col {
|
||||
case "name", "content":
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// UpdateIssueIndexerCols update an issue in the issue indexer, given changes
|
||||
// to the specified columns
|
||||
func UpdateIssueIndexerCols(issueID int64, cols ...string) {
|
||||
if updateNeededCols(cols) {
|
||||
UpdateIssueIndexer(issueID)
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateIssueIndexer add/update an issue to the issue indexer
|
||||
func UpdateIssueIndexer(issueID int64) {
|
||||
select {
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
|
|
@ -27,16 +26,14 @@ type Milestone struct {
|
|||
Completeness int // Percentage(1-100).
|
||||
IsOverDue bool `xorm:"-"`
|
||||
|
||||
DeadlineString string `xorm:"-"`
|
||||
Deadline time.Time `xorm:"-"`
|
||||
DeadlineUnix int64
|
||||
ClosedDate time.Time `xorm:"-"`
|
||||
ClosedDateUnix int64
|
||||
DeadlineString string `xorm:"-"`
|
||||
DeadlineUnix util.TimeStamp
|
||||
ClosedDateUnix util.TimeStamp
|
||||
}
|
||||
|
||||
// BeforeInsert is invoked from XORM before inserting an object of this type.
|
||||
func (m *Milestone) BeforeInsert() {
|
||||
m.DeadlineUnix = m.Deadline.Unix()
|
||||
m.DeadlineUnix = util.TimeStampNow()
|
||||
}
|
||||
|
||||
// BeforeUpdate is invoked from XORM before updating this object.
|
||||
|
|
@ -46,26 +43,20 @@ func (m *Milestone) BeforeUpdate() {
|
|||
} else {
|
||||
m.Completeness = 0
|
||||
}
|
||||
|
||||
m.DeadlineUnix = m.Deadline.Unix()
|
||||
m.ClosedDateUnix = m.ClosedDate.Unix()
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the value of a field of
|
||||
// this object.
|
||||
func (m *Milestone) AfterLoad() {
|
||||
m.NumOpenIssues = m.NumIssues - m.NumClosedIssues
|
||||
m.Deadline = time.Unix(m.DeadlineUnix, 0).Local()
|
||||
if m.Deadline.Year() == 9999 {
|
||||
if m.DeadlineUnix.Year() == 9999 {
|
||||
return
|
||||
}
|
||||
|
||||
m.DeadlineString = m.Deadline.Format("2006-01-02")
|
||||
if time.Now().Local().After(m.Deadline) {
|
||||
m.DeadlineString = m.DeadlineUnix.Format("2006-01-02")
|
||||
if util.TimeStampNow() >= m.DeadlineUnix {
|
||||
m.IsOverDue = true
|
||||
}
|
||||
|
||||
m.ClosedDate = time.Unix(m.ClosedDateUnix, 0).Local()
|
||||
}
|
||||
|
||||
// State returns string representation of milestone status.
|
||||
|
|
@ -87,10 +78,10 @@ func (m *Milestone) APIFormat() *api.Milestone {
|
|||
ClosedIssues: m.NumClosedIssues,
|
||||
}
|
||||
if m.IsClosed {
|
||||
apiMilestone.Closed = &m.ClosedDate
|
||||
apiMilestone.Closed = m.ClosedDateUnix.AsTimePtr()
|
||||
}
|
||||
if m.Deadline.Year() < 9999 {
|
||||
apiMilestone.Deadline = &m.Deadline
|
||||
if m.DeadlineUnix.Year() < 9999 {
|
||||
apiMilestone.Deadline = m.DeadlineUnix.AsTimePtr()
|
||||
}
|
||||
return apiMilestone
|
||||
}
|
||||
|
|
@ -174,31 +165,33 @@ func UpdateMilestone(m *Milestone) error {
|
|||
return updateMilestone(x, m)
|
||||
}
|
||||
|
||||
func countRepoMilestones(e Engine, repoID int64) int64 {
|
||||
count, _ := e.
|
||||
func countRepoMilestones(e Engine, repoID int64) (int64, error) {
|
||||
return e.
|
||||
Where("repo_id=?", repoID).
|
||||
Count(new(Milestone))
|
||||
return count
|
||||
}
|
||||
|
||||
func countRepoClosedMilestones(e Engine, repoID int64) int64 {
|
||||
closed, _ := e.
|
||||
func countRepoClosedMilestones(e Engine, repoID int64) (int64, error) {
|
||||
return e.
|
||||
Where("repo_id=? AND is_closed=?", repoID, true).
|
||||
Count(new(Milestone))
|
||||
return closed
|
||||
}
|
||||
|
||||
// CountRepoClosedMilestones returns number of closed milestones in given repository.
|
||||
func CountRepoClosedMilestones(repoID int64) int64 {
|
||||
func CountRepoClosedMilestones(repoID int64) (int64, error) {
|
||||
return countRepoClosedMilestones(x, repoID)
|
||||
}
|
||||
|
||||
// MilestoneStats returns number of open and closed milestones of given repository.
|
||||
func MilestoneStats(repoID int64) (open int64, closed int64) {
|
||||
open, _ = x.
|
||||
func MilestoneStats(repoID int64) (open int64, closed int64, err error) {
|
||||
open, err = x.
|
||||
Where("repo_id=? AND is_closed=?", repoID, false).
|
||||
Count(new(Milestone))
|
||||
return open, CountRepoClosedMilestones(repoID)
|
||||
if err != nil {
|
||||
return 0, 0, nil
|
||||
}
|
||||
closed, err = CountRepoClosedMilestones(repoID)
|
||||
return open, closed, err
|
||||
}
|
||||
|
||||
// ChangeMilestoneStatus changes the milestone open/closed status.
|
||||
|
|
@ -219,8 +212,17 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
repo.NumMilestones = int(countRepoMilestones(sess, repo.ID))
|
||||
repo.NumClosedMilestones = int(countRepoClosedMilestones(sess, repo.ID))
|
||||
numMilestones, err := countRepoMilestones(sess, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numClosedMilestones, err := countRepoClosedMilestones(sess, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repo.NumMilestones = int(numMilestones)
|
||||
repo.NumClosedMilestones = int(numClosedMilestones)
|
||||
|
||||
if _, err = sess.ID(repo.ID).Cols("num_milestones, num_closed_milestones").Update(repo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -291,7 +293,7 @@ func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilesto
|
|||
}
|
||||
}
|
||||
|
||||
return updateIssue(e, issue)
|
||||
return updateIssueCols(e, issue, "milestone_id")
|
||||
}
|
||||
|
||||
// ChangeMilestoneAssign changes assignment of milestone for issue.
|
||||
|
|
@ -333,8 +335,17 @@ func DeleteMilestoneByRepoID(repoID, id int64) error {
|
|||
return err
|
||||
}
|
||||
|
||||
repo.NumMilestones = int(countRepoMilestones(sess, repo.ID))
|
||||
repo.NumClosedMilestones = int(countRepoClosedMilestones(sess, repo.ID))
|
||||
numMilestones, err := countRepoMilestones(sess, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
numClosedMilestones, err := countRepoClosedMilestones(sess, repo.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
repo.NumMilestones = int(numMilestones)
|
||||
repo.NumClosedMilestones = int(numClosedMilestones)
|
||||
|
||||
if _, err = sess.ID(repo.ID).Cols("num_milestones, num_closed_milestones").Update(repo); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -28,7 +29,7 @@ func TestMilestone_APIFormat(t *testing.T) {
|
|||
IsClosed: false,
|
||||
NumOpenIssues: 5,
|
||||
NumClosedIssues: 6,
|
||||
Deadline: time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC),
|
||||
DeadlineUnix: util.TimeStamp(time.Date(2000, time.January, 1, 0, 0, 0, 0, time.UTC).Unix()),
|
||||
}
|
||||
assert.Equal(t, api.Milestone{
|
||||
ID: milestone.ID,
|
||||
|
|
@ -37,7 +38,7 @@ func TestMilestone_APIFormat(t *testing.T) {
|
|||
Description: milestone.Content,
|
||||
OpenIssues: milestone.NumOpenIssues,
|
||||
ClosedIssues: milestone.NumClosedIssues,
|
||||
Deadline: &milestone.Deadline,
|
||||
Deadline: milestone.DeadlineUnix.AsTimePtr(),
|
||||
}, *milestone.APIFormat())
|
||||
}
|
||||
|
||||
|
|
@ -145,31 +146,42 @@ func TestCountRepoMilestones(t *testing.T) {
|
|||
assert.NoError(t, PrepareTestDatabase())
|
||||
test := func(repoID int64) {
|
||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
|
||||
assert.EqualValues(t, repo.NumMilestones, countRepoMilestones(x, repoID))
|
||||
count, err := countRepoMilestones(x, repoID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, repo.NumMilestones, count)
|
||||
}
|
||||
test(1)
|
||||
test(2)
|
||||
test(3)
|
||||
assert.EqualValues(t, 0, countRepoMilestones(x, NonexistentID))
|
||||
|
||||
count, err := countRepoMilestones(x, NonexistentID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
}
|
||||
|
||||
func TestCountRepoClosedMilestones(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
test := func(repoID int64) {
|
||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
|
||||
assert.EqualValues(t, repo.NumClosedMilestones, CountRepoClosedMilestones(repoID))
|
||||
count, err := CountRepoClosedMilestones(repoID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, repo.NumClosedMilestones, count)
|
||||
}
|
||||
test(1)
|
||||
test(2)
|
||||
test(3)
|
||||
assert.EqualValues(t, 0, countRepoMilestones(x, NonexistentID))
|
||||
|
||||
count, err := CountRepoClosedMilestones(NonexistentID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, count)
|
||||
}
|
||||
|
||||
func TestMilestoneStats(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
test := func(repoID int64) {
|
||||
repo := AssertExistsAndLoadBean(t, &Repository{ID: repoID}).(*Repository)
|
||||
open, closed := MilestoneStats(repoID)
|
||||
open, closed, err := MilestoneStats(repoID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, repo.NumMilestones-repo.NumClosedMilestones, open)
|
||||
assert.EqualValues(t, repo.NumClosedMilestones, closed)
|
||||
}
|
||||
|
|
@ -177,7 +189,8 @@ func TestMilestoneStats(t *testing.T) {
|
|||
test(2)
|
||||
test(3)
|
||||
|
||||
open, closed := MilestoneStats(NonexistentID)
|
||||
open, closed, err := MilestoneStats(NonexistentID)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, open)
|
||||
assert.EqualValues(t, 0, closed)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,9 +7,9 @@ package models
|
|||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
"github.com/go-xorm/xorm"
|
||||
|
|
@ -17,19 +17,13 @@ import (
|
|||
|
||||
// Reaction represents a reactions on issues and comments.
|
||||
type Reaction struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
User *User `xorm:"-"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (s *Reaction) AfterLoad() {
|
||||
s.Created = time.Unix(s.CreatedUnix, 0).Local()
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
User *User `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
// FindReactionsOptions describes the conditions to Find reactions
|
||||
|
|
|
|||
|
|
@ -7,26 +7,16 @@ package models
|
|||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// Stopwatch represents a stopwatch for time tracking.
|
||||
type Stopwatch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
UserID int64 `xorm:"INDEX"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
}
|
||||
|
||||
// BeforeInsert will be invoked by XORM before inserting a record
|
||||
// representing this object.
|
||||
func (s *Stopwatch) BeforeInsert() {
|
||||
s.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (s *Stopwatch) AfterLoad() {
|
||||
s.Created = time.Unix(s.CreatedUnix, 0).Local()
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
UserID int64 `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
}
|
||||
|
||||
func getStopwatch(e Engine, userID, issueID int64) (sw *Stopwatch, exists bool, err error) {
|
||||
|
|
@ -61,7 +51,7 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
|||
}
|
||||
if exists {
|
||||
// Create tracked time out of the time difference between start date and actual date
|
||||
timediff := time.Now().Unix() - sw.CreatedUnix
|
||||
timediff := time.Now().Unix() - int64(sw.CreatedUnix)
|
||||
|
||||
// Create TrackedTime
|
||||
tt := &TrackedTime{
|
||||
|
|
@ -92,7 +82,6 @@ func CreateOrStopIssueStopwatch(user *User, issue *Issue) error {
|
|||
sw = &Stopwatch{
|
||||
UserID: user.ID,
|
||||
IssueID: issue.ID,
|
||||
Created: time.Now(),
|
||||
}
|
||||
|
||||
if _, err := x.Insert(sw); err != nil {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,8 @@ package models
|
|||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
|
@ -62,7 +63,7 @@ func TestCreateOrStopIssueStopwatch(t *testing.T) {
|
|||
|
||||
assert.NoError(t, CreateOrStopIssueStopwatch(user3, issue1))
|
||||
sw := AssertExistsAndLoadBean(t, &Stopwatch{UserID: 3, IssueID: 1}).(*Stopwatch)
|
||||
assert.Equal(t, true, sw.Created.Before(time.Now()))
|
||||
assert.Equal(t, true, sw.CreatedUnix <= util.TimeStampNow())
|
||||
|
||||
assert.NoError(t, CreateOrStopIssueStopwatch(user2, issue2))
|
||||
AssertNotExistsBean(t, &Stopwatch{UserID: 2, IssueID: 2})
|
||||
|
|
|
|||
|
|
@ -166,5 +166,5 @@ func TestUpdateIssueCols(t *testing.T) {
|
|||
updatedIssue := AssertExistsAndLoadBean(t, &Issue{ID: issue.ID}).(*Issue)
|
||||
assert.EqualValues(t, newTitle, updatedIssue.Title)
|
||||
assert.EqualValues(t, prevContent, updatedIssue.Content)
|
||||
AssertInt64InRange(t, now, then, updatedIssue.UpdatedUnix)
|
||||
AssertInt64InRange(t, now, then, int64(updatedIssue.UpdatedUnix))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ package models
|
|||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/go-xorm/builder"
|
||||
|
|
@ -24,7 +25,7 @@ type TrackedTime struct {
|
|||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (t *TrackedTime) AfterLoad() {
|
||||
t.Created = time.Unix(t.CreatedUnix, 0).Local()
|
||||
t.Created = time.Unix(t.CreatedUnix, 0).In(setting.UILocation)
|
||||
}
|
||||
|
||||
// APIFormat converts TrackedTime to API format
|
||||
|
|
|
|||
|
|
@ -4,42 +4,16 @@
|
|||
|
||||
package models
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
import "code.gitea.io/gitea/modules/util"
|
||||
|
||||
// IssueWatch is connection request for receiving issue notification.
|
||||
type IssueWatch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"UNIQUE(watch) NOT NULL"`
|
||||
IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"`
|
||||
IsWatching bool `xorm:"NOT NULL"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"NOT NULL"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"NOT NULL"`
|
||||
}
|
||||
|
||||
// BeforeInsert is invoked from XORM before inserting an object of this type.
|
||||
func (iw *IssueWatch) BeforeInsert() {
|
||||
var (
|
||||
t = time.Now()
|
||||
u = t.Unix()
|
||||
)
|
||||
iw.Created = t
|
||||
iw.CreatedUnix = u
|
||||
iw.Updated = t
|
||||
iw.UpdatedUnix = u
|
||||
}
|
||||
|
||||
// BeforeUpdate is invoked from XORM before updating an object of this type.
|
||||
func (iw *IssueWatch) BeforeUpdate() {
|
||||
var (
|
||||
t = time.Now()
|
||||
u = t.Unix()
|
||||
)
|
||||
iw.Updated = t
|
||||
iw.UpdatedUnix = u
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"UNIQUE(watch) NOT NULL"`
|
||||
IssueID int64 `xorm:"UNIQUE(watch) NOT NULL"`
|
||||
IsWatching bool `xorm:"NOT NULL"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created NOT NULL"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated NOT NULL"`
|
||||
}
|
||||
|
||||
// CreateOrUpdateIssueWatch set watching for a user and issue
|
||||
|
|
|
|||
|
|
@ -2,18 +2,18 @@ package models
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// LFSMetaObject stores metadata for LFS tracked files.
|
||||
type LFSMetaObject struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Oid string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Size int64 `xorm:"NOT NULL"`
|
||||
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Existing bool `xorm:"-"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Oid string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Size int64 `xorm:"NOT NULL"`
|
||||
RepositoryID int64 `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||
Existing bool `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
}
|
||||
|
||||
// LFSTokenResponse defines the JSON structure in which the JWT token is stored.
|
||||
|
|
@ -105,8 +105,3 @@ func (repo *Repository) RemoveLFSMetaObjectByOid(oid string) error {
|
|||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
||||
// AfterLoad stores the LFSMetaObject creation time in the database as local time.
|
||||
func (m *LFSMetaObject) AfterLoad() {
|
||||
m.Created = time.Unix(m.CreatedUnix, 0).Local()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ func (l *LFSLock) AfterLoad() {
|
|||
}
|
||||
|
||||
func cleanPath(p string) string {
|
||||
return strings.ToLower(path.Clean(p))
|
||||
return path.Clean(p)
|
||||
}
|
||||
|
||||
// APIFormat convert a Release to lfs.LFSLock
|
||||
|
|
@ -73,8 +73,8 @@ func CreateLFSLock(lock *LFSLock) (*LFSLock, error) {
|
|||
// GetLFSLock returns release by given path.
|
||||
func GetLFSLock(repoID int64, path string) (*LFSLock, error) {
|
||||
path = cleanPath(path)
|
||||
rel := &LFSLock{RepoID: repoID, Path: path}
|
||||
has, err := x.Get(rel)
|
||||
rel := &LFSLock{RepoID: repoID}
|
||||
has, err := x.Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@ import (
|
|||
"net/smtp"
|
||||
"net/textproto"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-macaron/binding"
|
||||
|
|
@ -23,6 +22,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/auth/oauth2"
|
||||
"code.gitea.io/gitea/modules/auth/pam"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// LoginType represents an login type.
|
||||
|
|
@ -147,10 +147,8 @@ type LoginSource struct {
|
|||
IsSyncEnabled bool `xorm:"INDEX NOT NULL DEFAULT false"`
|
||||
Cfg core.Conversion `xorm:"TEXT"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// Cell2Int64 converts a xorm.Cell type to int64,
|
||||
|
|
@ -183,12 +181,6 @@ func (source *LoginSource) BeforeSet(colName string, val xorm.Cell) {
|
|||
}
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (source *LoginSource) AfterLoad() {
|
||||
source.Created = time.Unix(source.CreatedUnix, 0).Local()
|
||||
source.Updated = time.Unix(source.UpdatedUnix, 0).Local()
|
||||
}
|
||||
|
||||
// TypeName return name of this login source type.
|
||||
func (source *LoginSource) TypeName() string {
|
||||
return LoginNames[source.Type]
|
||||
|
|
|
|||
|
|
@ -59,6 +59,10 @@ type Version struct {
|
|||
Version int64
|
||||
}
|
||||
|
||||
func emptyMigration(x *xorm.Engine) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// This is a sequence of migrations. Add new migrations to the bottom of the list.
|
||||
// If you want to "retire" a migration, remove it from the top of the list and
|
||||
// update minDBVersion accordingly
|
||||
|
|
@ -127,17 +131,17 @@ var migrations = []Migration{
|
|||
// v38 -> v39
|
||||
NewMigration("remove commits and settings unit types", removeCommitsUnitType),
|
||||
// v39 -> v40
|
||||
NewMigration("adds time tracking and stopwatches", addTimetracking),
|
||||
// v40 -> v41
|
||||
NewMigration("migrate protected branch struct", migrateProtectedBranchStruct),
|
||||
// v41 -> v42
|
||||
NewMigration("add default value to user prohibit_login", addDefaultValueToUserProhibitLogin),
|
||||
// v42 -> v43
|
||||
NewMigration("add tags to releases and sync existing repositories", releaseAddColumnIsTagAndSyncTags),
|
||||
// v43 -> v44
|
||||
// v40 -> v41
|
||||
NewMigration("fix protected branch can push value to false", fixProtectedBranchCanPushValue),
|
||||
// v44 -> v45
|
||||
// v41 -> v42
|
||||
NewMigration("remove duplicate unit types", removeDuplicateUnitTypes),
|
||||
// v42 -> v43
|
||||
NewMigration("empty step", emptyMigration),
|
||||
// v43 -> v44
|
||||
NewMigration("empty step", emptyMigration),
|
||||
// v44 -> v45
|
||||
NewMigration("empty step", emptyMigration),
|
||||
// v45 -> v46
|
||||
NewMigration("remove index column from repo_unit table", removeIndexColumnFromRepoUnitTable),
|
||||
// v46 -> v47
|
||||
|
|
@ -147,8 +151,14 @@ var migrations = []Migration{
|
|||
// v48 -> v49
|
||||
NewMigration("add repo indexer status", addRepoIndexerStatus),
|
||||
// v49 -> v50
|
||||
NewMigration("add lfs lock table", addLFSLock),
|
||||
NewMigration("adds time tracking and stopwatches", addTimetracking),
|
||||
// v50 -> v51
|
||||
NewMigration("migrate protected branch struct", migrateProtectedBranchStruct),
|
||||
// v51 -> v52
|
||||
NewMigration("add default value to user prohibit_login", addDefaultValueToUserProhibitLogin),
|
||||
// v52 -> v53
|
||||
NewMigration("add lfs lock table", addLFSLock),
|
||||
// v53 -> v54
|
||||
NewMigration("add reactions", addReactions),
|
||||
// v51 -> v52
|
||||
NewMigration("add issue_dependencies", addIssueDependencies),
|
||||
|
|
|
|||
|
|
@ -6,69 +6,52 @@ package migrations
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addTimetracking(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Index int
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
}
|
||||
// ReleaseV39 describes the added field for Release
|
||||
type ReleaseV39 struct {
|
||||
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
// Stopwatch see models/issue_stopwatch.go
|
||||
type Stopwatch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
UserID int64 `xorm:"INDEX"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
}
|
||||
// TableName will be invoked by XORM to customrize the table name
|
||||
func (*ReleaseV39) TableName() string {
|
||||
return "release"
|
||||
}
|
||||
|
||||
// TrackedTime see models/issue_tracked_time.go
|
||||
type TrackedTime struct {
|
||||
ID int64 `xorm:"pk autoincr" json:"id"`
|
||||
IssueID int64 `xorm:"INDEX" json:"issue_id"`
|
||||
UserID int64 `xorm:"INDEX" json:"user_id"`
|
||||
Created time.Time `xorm:"-" json:"created"`
|
||||
CreatedUnix int64 `json:"-"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(Stopwatch)); err != nil {
|
||||
func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
|
||||
if err := x.Sync2(new(ReleaseV39)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
if err := x.Sync2(new(TrackedTime)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
//Updating existing issue units
|
||||
units := make([]*RepoUnit, 0, 100)
|
||||
err := x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repo units: %v", err)
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
|
||||
// For the sake of SQLite3, we can't use x.Iterate here.
|
||||
offset := 0
|
||||
pageSize := 20
|
||||
for {
|
||||
repos := make([]*models.Repository, 0, pageSize)
|
||||
if err := x.Table("repository").Asc("id").Limit(pageSize, offset).Find(&repos); err != nil {
|
||||
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
|
||||
}
|
||||
if _, ok := unit.Config["EnableTimetracker"]; !ok {
|
||||
unit.Config["EnableTimetracker"] = setting.Service.DefaultEnableTimetracking
|
||||
for _, repo := range repos {
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Warn("OpenRepository: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||
log.Warn("SyncReleasesWithTags: %v", err)
|
||||
}
|
||||
}
|
||||
if _, ok := unit.Config["AllowOnlyContributorsToTrackTime"]; !ok {
|
||||
unit.Config["AllowOnlyContributorsToTrackTime"] = setting.Service.DefaultAllowOnlyContributorsToTrackTime
|
||||
}
|
||||
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
return err
|
||||
if len(repos) < pageSize {
|
||||
break
|
||||
}
|
||||
offset += pageSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,50 +6,21 @@ package migrations
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func migrateProtectedBranchStruct(x *xorm.Engine) error {
|
||||
func fixProtectedBranchCanPushValue(x *xorm.Engine) error {
|
||||
type ProtectedBranch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||
BranchName string `xorm:"UNIQUE(s)"`
|
||||
CanPush bool
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64
|
||||
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
var pbs []ProtectedBranch
|
||||
err := x.Find(&pbs)
|
||||
if err != nil {
|
||||
return err
|
||||
if err := x.Sync2(new(ProtectedBranch)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
|
||||
for _, pb := range pbs {
|
||||
if pb.CanPush {
|
||||
if _, err = x.ID(pb.ID).Delete(new(ProtectedBranch)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case setting.UseSQLite3:
|
||||
log.Warn("Unable to drop columns in SQLite")
|
||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
||||
if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil {
|
||||
return fmt.Errorf("DROP COLUMN can_push: %v", err)
|
||||
}
|
||||
default:
|
||||
log.Fatal(4, "Unrecognized DB")
|
||||
}
|
||||
|
||||
return nil
|
||||
_, err := x.Cols("can_push").Update(&ProtectedBranch{
|
||||
CanPush: false,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,36 +7,63 @@ package migrations
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addDefaultValueToUserProhibitLogin(x *xorm.Engine) (err error) {
|
||||
user := &models.User{
|
||||
ProhibitLogin: false,
|
||||
func removeDuplicateUnitTypes(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
RepoID int64
|
||||
Type int
|
||||
}
|
||||
|
||||
if _, err := x.Where("`prohibit_login` IS NULL").Cols("prohibit_login").Update(user); err != nil {
|
||||
// Enumerate all the unit types
|
||||
const (
|
||||
UnitTypeCode = iota + 1 // 1 code
|
||||
UnitTypeIssues // 2 issues
|
||||
UnitTypePullRequests // 3 PRs
|
||||
UnitTypeReleases // 4 Releases
|
||||
UnitTypeWiki // 5 Wiki
|
||||
UnitTypeExternalWiki // 6 ExternalWiki
|
||||
UnitTypeExternalTracker // 7 ExternalTracker
|
||||
)
|
||||
|
||||
var externalIssueRepoUnits []RepoUnit
|
||||
err := x.Where("type = ?", UnitTypeExternalTracker).Find(&externalIssueRepoUnits)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repositories: %v", err)
|
||||
}
|
||||
|
||||
var externalWikiRepoUnits []RepoUnit
|
||||
err = x.Where("type = ?", UnitTypeExternalWiki).Find(&externalWikiRepoUnits)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repositories: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
dialect := x.Dialect().DriverName()
|
||||
|
||||
switch dialect {
|
||||
case "mysql":
|
||||
_, err = x.Exec("ALTER TABLE user MODIFY `prohibit_login` tinyint(1) NOT NULL DEFAULT 0")
|
||||
case "postgres":
|
||||
_, err = x.Exec("ALTER TABLE \"user\" ALTER COLUMN `prohibit_login` SET NOT NULL, ALTER COLUMN `prohibit_login` SET DEFAULT false")
|
||||
case "mssql":
|
||||
// xorm already set DEFAULT 0 for data type BIT in mssql
|
||||
_, err = x.Exec(`ALTER TABLE [user] ALTER COLUMN "prohibit_login" BIT NOT NULL`)
|
||||
case "sqlite3":
|
||||
for _, repoUnit := range externalIssueRepoUnits {
|
||||
if _, err = sess.Delete(&RepoUnit{
|
||||
RepoID: repoUnit.RepoID,
|
||||
Type: UnitTypeIssues,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Delete repo unit: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Error changing user prohibit_login column definition: %v", err)
|
||||
for _, repoUnit := range externalWikiRepoUnits {
|
||||
if _, err = sess.Delete(&RepoUnit{
|
||||
RepoID: repoUnit.RepoID,
|
||||
Type: UnitTypeWiki,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Delete repo unit: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return err
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,57 +0,0 @@
|
|||
// Copyright 2017 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 migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
// ReleaseV39 describes the added field for Release
|
||||
type ReleaseV39 struct {
|
||||
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
// TableName will be invoked by XORM to customrize the table name
|
||||
func (*ReleaseV39) TableName() string {
|
||||
return "release"
|
||||
}
|
||||
|
||||
func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
|
||||
if err := x.Sync2(new(ReleaseV39)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
|
||||
// For the sake of SQLite3, we can't use x.Iterate here.
|
||||
offset := 0
|
||||
pageSize := 20
|
||||
for {
|
||||
repos := make([]*models.Repository, 0, pageSize)
|
||||
if err := x.Table("repository").Asc("id").Limit(pageSize, offset).Find(&repos); err != nil {
|
||||
return fmt.Errorf("select repos [offset: %d]: %v", offset, err)
|
||||
}
|
||||
for _, repo := range repos {
|
||||
gitRepo, err := git.OpenRepository(repo.RepoPath())
|
||||
if err != nil {
|
||||
log.Warn("OpenRepository: %v", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
|
||||
log.Warn("SyncReleasesWithTags: %v", err)
|
||||
}
|
||||
}
|
||||
if len(repos) < pageSize {
|
||||
break
|
||||
}
|
||||
offset += pageSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
// Copyright 2017 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 migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func fixProtectedBranchCanPushValue(x *xorm.Engine) error {
|
||||
type ProtectedBranch struct {
|
||||
CanPush bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(ProtectedBranch)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
|
||||
_, err := x.Cols("can_push").Update(&ProtectedBranch{
|
||||
CanPush: false,
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
|
@ -1,69 +0,0 @@
|
|||
// Copyright 2017 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 migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func removeDuplicateUnitTypes(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
RepoID int64
|
||||
Type int
|
||||
}
|
||||
|
||||
// Enumerate all the unit types
|
||||
const (
|
||||
UnitTypeCode = iota + 1 // 1 code
|
||||
UnitTypeIssues // 2 issues
|
||||
UnitTypePullRequests // 3 PRs
|
||||
UnitTypeReleases // 4 Releases
|
||||
UnitTypeWiki // 5 Wiki
|
||||
UnitTypeExternalWiki // 6 ExternalWiki
|
||||
UnitTypeExternalTracker // 7 ExternalTracker
|
||||
)
|
||||
|
||||
var externalIssueRepoUnits []RepoUnit
|
||||
err := x.Where("type = ?", UnitTypeExternalTracker).Find(&externalIssueRepoUnits)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repositories: %v", err)
|
||||
}
|
||||
|
||||
var externalWikiRepoUnits []RepoUnit
|
||||
err = x.Where("type = ?", UnitTypeExternalWiki).Find(&externalWikiRepoUnits)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repositories: %v", err)
|
||||
}
|
||||
|
||||
sess := x.NewSession()
|
||||
defer sess.Close()
|
||||
|
||||
if err := sess.Begin(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, repoUnit := range externalIssueRepoUnits {
|
||||
if _, err = sess.Delete(&RepoUnit{
|
||||
RepoID: repoUnit.RepoID,
|
||||
Type: UnitTypeIssues,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Delete repo unit: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
for _, repoUnit := range externalWikiRepoUnits {
|
||||
if _, err = sess.Delete(&RepoUnit{
|
||||
RepoID: repoUnit.RepoID,
|
||||
Type: UnitTypeWiki,
|
||||
}); err != nil {
|
||||
return fmt.Errorf("Delete repo unit: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return sess.Commit()
|
||||
}
|
||||
|
|
@ -5,10 +5,9 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
|
|
@ -18,7 +17,8 @@ func removeIndexColumnFromRepoUnitTable(x *xorm.Engine) (err error) {
|
|||
log.Warn("Unable to drop columns in SQLite")
|
||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
||||
if _, err := x.Exec("ALTER TABLE repo_unit DROP COLUMN `index`"); err != nil {
|
||||
return fmt.Errorf("DROP COLUMN index: %v", err)
|
||||
// Ignoring this error in case we run this migration second time (after migration reordering)
|
||||
log.Warn("DROP COLUMN index: %v", err)
|
||||
}
|
||||
default:
|
||||
log.Fatal(4, "Unrecognized DB")
|
||||
|
|
|
|||
|
|
@ -8,24 +8,66 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addLFSLock(x *xorm.Engine) error {
|
||||
// LFSLock see models/lfs_lock.go
|
||||
type LFSLock struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
Owner *models.User `xorm:"-"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
Path string `xorm:"TEXT"`
|
||||
Created time.Time `xorm:"created"`
|
||||
func addTimetracking(x *xorm.Engine) error {
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(LFSLock)); err != nil {
|
||||
// Stopwatch see models/issue_stopwatch.go
|
||||
type Stopwatch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
IssueID int64 `xorm:"INDEX"`
|
||||
UserID int64 `xorm:"INDEX"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
}
|
||||
|
||||
// TrackedTime see models/issue_tracked_time.go
|
||||
type TrackedTime struct {
|
||||
ID int64 `xorm:"pk autoincr" json:"id"`
|
||||
IssueID int64 `xorm:"INDEX" json:"issue_id"`
|
||||
UserID int64 `xorm:"INDEX" json:"user_id"`
|
||||
Created time.Time `xorm:"-" json:"created"`
|
||||
CreatedUnix int64 `json:"-"`
|
||||
Time int64 `json:"time"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(Stopwatch)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
if err := x.Sync2(new(TrackedTime)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
//Updating existing issue units
|
||||
units := make([]*RepoUnit, 0, 100)
|
||||
err := x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repo units: %v", err)
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
}
|
||||
if _, ok := unit.Config["EnableTimetracker"]; !ok {
|
||||
unit.Config["EnableTimetracker"] = setting.Service.DefaultEnableTimetracking
|
||||
}
|
||||
if _, ok := unit.Config["AllowOnlyContributorsToTrackTime"]; !ok {
|
||||
unit.Config["AllowOnlyContributorsToTrackTime"] = setting.Service.DefaultAllowOnlyContributorsToTrackTime
|
||||
}
|
||||
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,24 +5,51 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addReactions(x *xorm.Engine) error {
|
||||
// Reaction see models/issue_reaction.go
|
||||
type Reaction struct {
|
||||
func migrateProtectedBranchStruct(x *xorm.Engine) error {
|
||||
type ProtectedBranch struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
RepoID int64 `xorm:"UNIQUE(s)"`
|
||||
BranchName string `xorm:"UNIQUE(s)"`
|
||||
CanPush bool
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(Reaction)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
var pbs []ProtectedBranch
|
||||
err := x.Find(&pbs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, pb := range pbs {
|
||||
if pb.CanPush {
|
||||
if _, err = x.ID(pb.ID).Delete(new(ProtectedBranch)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch {
|
||||
case setting.UseSQLite3:
|
||||
log.Warn("Unable to drop columns in SQLite")
|
||||
case setting.UseMySQL, setting.UsePostgreSQL, setting.UseMSSQL, setting.UseTiDB:
|
||||
if _, err := x.Exec("ALTER TABLE protected_branch DROP COLUMN can_push"); err != nil {
|
||||
// Ignoring this error in case we run this migration second time (after migration reordering)
|
||||
log.Warn("DROP COLUMN can_push (skipping): %v", err)
|
||||
}
|
||||
default:
|
||||
log.Fatal(4, "Unrecognized DB")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,56 +5,38 @@
|
|||
package migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addIssueDependencies(x *xorm.Engine) (err error) {
|
||||
|
||||
type IssueDependency struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
UserID int64 `xorm:"NOT NULL"`
|
||||
IssueID int64 `xorm:"NOT NULL"`
|
||||
DependencyID int64 `xorm:"NOT NULL"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
func addDefaultValueToUserProhibitLogin(x *xorm.Engine) (err error) {
|
||||
user := &models.User{
|
||||
ProhibitLogin: false,
|
||||
}
|
||||
|
||||
if err = x.Sync(new(IssueDependency)); err != nil {
|
||||
return fmt.Errorf("Error creating issue_dependency_table column definition: %v", err)
|
||||
if _, err := x.Where("`prohibit_login` IS NULL").Cols("prohibit_login").Update(user); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// RepoUnit describes all units of a repository
|
||||
type RepoUnit struct {
|
||||
ID int64
|
||||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type int `xorm:"INDEX(s)"`
|
||||
Config map[string]interface{} `xorm:"JSON"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
dialect := x.Dialect().DriverName()
|
||||
|
||||
switch dialect {
|
||||
case "mysql":
|
||||
_, err = x.Exec("ALTER TABLE user MODIFY `prohibit_login` tinyint(1) NOT NULL DEFAULT 0")
|
||||
case "postgres":
|
||||
_, err = x.Exec("ALTER TABLE \"user\" ALTER COLUMN `prohibit_login` SET NOT NULL, ALTER COLUMN `prohibit_login` SET DEFAULT false")
|
||||
case "mssql":
|
||||
// xorm already set DEFAULT 0 for data type BIT in mssql
|
||||
_, err = x.Exec(`ALTER TABLE [user] ALTER COLUMN "prohibit_login" BIT NOT NULL`)
|
||||
case "sqlite3":
|
||||
}
|
||||
|
||||
//Updating existing issue units
|
||||
units := make([]*RepoUnit, 0, 100)
|
||||
err = x.Where("`type` = ?", V16UnitTypeIssues).Find(&units)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Query repo units: %v", err)
|
||||
}
|
||||
for _, unit := range units {
|
||||
if unit.Config == nil {
|
||||
unit.Config = make(map[string]interface{})
|
||||
}
|
||||
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
||||
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
||||
}
|
||||
if _, err := x.ID(unit.ID).Cols("config").Update(unit); err != nil {
|
||||
return err
|
||||
}
|
||||
// Ignoring this error in case we run this migration second time (after migration reordering)
|
||||
log.Warn("Error changing user prohibit_login column definition (skipping): %v", err)
|
||||
}
|
||||
|
||||
return err
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
31
models/migrations/v52.go
Normal file
31
models/migrations/v52.go
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
// Copyright 2017 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 migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/models"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addLFSLock(x *xorm.Engine) error {
|
||||
// LFSLock see models/lfs_lock.go
|
||||
type LFSLock struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
RepoID int64 `xorm:"INDEX NOT NULL"`
|
||||
Owner *models.User `xorm:"-"`
|
||||
OwnerID int64 `xorm:"INDEX NOT NULL"`
|
||||
Path string `xorm:"TEXT"`
|
||||
Created time.Time `xorm:"created"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(LFSLock)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
28
models/migrations/v53.go
Normal file
28
models/migrations/v53.go
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2017 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 migrations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
)
|
||||
|
||||
func addReactions(x *xorm.Engine) error {
|
||||
// Reaction see models/issue_reaction.go
|
||||
type Reaction struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
Type string `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
IssueID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CommentID int64 `xorm:"INDEX UNIQUE(s)"`
|
||||
UserID int64 `xorm:"INDEX UNIQUE(s) NOT NULL"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
}
|
||||
|
||||
if err := x.Sync2(new(Reaction)); err != nil {
|
||||
return fmt.Errorf("Sync2: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
1
models/migrations/v54.go
Normal file
1
models/migrations/v54.go
Normal file
|
|
@ -0,0 +1 @@
|
|||
package migrations
|
||||
|
|
@ -6,7 +6,8 @@ package models
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
type (
|
||||
|
|
@ -51,32 +52,8 @@ type Notification struct {
|
|||
Issue *Issue `xorm:"-"`
|
||||
Repository *Repository `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX NOT NULL"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX NOT NULL"`
|
||||
}
|
||||
|
||||
// BeforeInsert runs while inserting a record
|
||||
func (n *Notification) BeforeInsert() {
|
||||
var (
|
||||
now = time.Now()
|
||||
nowUnix = now.Unix()
|
||||
)
|
||||
n.Created = now
|
||||
n.CreatedUnix = nowUnix
|
||||
n.Updated = now
|
||||
n.UpdatedUnix = nowUnix
|
||||
}
|
||||
|
||||
// BeforeUpdate runs while updating a record
|
||||
func (n *Notification) BeforeUpdate() {
|
||||
var (
|
||||
now = time.Now()
|
||||
nowUnix = now.Unix()
|
||||
)
|
||||
n.Updated = now
|
||||
n.UpdatedUnix = nowUnix
|
||||
CreatedUnix util.TimeStamp `xorm:"created INDEX NOT NULL"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated INDEX NOT NULL"`
|
||||
}
|
||||
|
||||
// CreateOrUpdateIssueNotifications creates an issue notification
|
||||
|
|
@ -212,6 +189,7 @@ func getIssueNotification(e Engine, userID, issueID int64) (*Notification, error
|
|||
func NotificationsForUser(user *User, statuses []NotificationStatus, page, perPage int) ([]*Notification, error) {
|
||||
return notificationsForUser(x, user, statuses, page, perPage)
|
||||
}
|
||||
|
||||
func notificationsForUser(e Engine, user *User, statuses []NotificationStatus, page, perPage int) (notifications []*Notification, err error) {
|
||||
if len(statuses) == 0 {
|
||||
return
|
||||
|
|
@ -311,3 +289,13 @@ func getNotificationByID(notificationID int64) (*Notification, error) {
|
|||
|
||||
return notification, nil
|
||||
}
|
||||
|
||||
// UpdateNotificationStatuses updates the statuses of all of a user's notifications that are of the currentStatus type to the desiredStatus
|
||||
func UpdateNotificationStatuses(user *User, currentStatus NotificationStatus, desiredStatus NotificationStatus) error {
|
||||
n := &Notification{Status: desiredStatus, UpdatedBy: user.ID}
|
||||
_, err := x.
|
||||
Where("user_id = ? AND status = ?", user.ID, currentStatus).
|
||||
Cols("status", "updated_by", "updated_unix").
|
||||
Update(n)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,9 +31,11 @@ func TestNotificationsForUser(t *testing.T) {
|
|||
statuses := []NotificationStatus{NotificationStatusRead, NotificationStatusUnread}
|
||||
notfs, err := NotificationsForUser(user, statuses, 1, 10)
|
||||
assert.NoError(t, err)
|
||||
if assert.Len(t, notfs, 1) {
|
||||
if assert.Len(t, notfs, 2) {
|
||||
assert.EqualValues(t, 2, notfs[0].ID)
|
||||
assert.EqualValues(t, user.ID, notfs[0].UserID)
|
||||
assert.EqualValues(t, 4, notfs[1].ID)
|
||||
assert.EqualValues(t, user.ID, notfs[1].UserID)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,12 +59,12 @@ func TestNotification_GetIssue(t *testing.T) {
|
|||
|
||||
func TestGetNotificationCount(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
cnt, err := GetNotificationCount(user, NotificationStatusUnread)
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
|
||||
cnt, err := GetNotificationCount(user, NotificationStatusRead)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 0, cnt)
|
||||
|
||||
cnt, err = GetNotificationCount(user, NotificationStatusRead)
|
||||
cnt, err = GetNotificationCount(user, NotificationStatusUnread)
|
||||
assert.NoError(t, err)
|
||||
assert.EqualValues(t, 1, cnt)
|
||||
}
|
||||
|
|
@ -79,3 +81,21 @@ func TestSetNotificationStatus(t *testing.T) {
|
|||
assert.Error(t, SetNotificationStatus(1, user, NotificationStatusRead))
|
||||
assert.Error(t, SetNotificationStatus(NonexistentID, user, NotificationStatusRead))
|
||||
}
|
||||
|
||||
func TestUpdateNotificationStatuses(t *testing.T) {
|
||||
assert.NoError(t, PrepareTestDatabase())
|
||||
user := AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
|
||||
notfUnread := AssertExistsAndLoadBean(t,
|
||||
&Notification{UserID: user.ID, Status: NotificationStatusUnread}).(*Notification)
|
||||
notfRead := AssertExistsAndLoadBean(t,
|
||||
&Notification{UserID: user.ID, Status: NotificationStatusRead}).(*Notification)
|
||||
notfPinned := AssertExistsAndLoadBean(t,
|
||||
&Notification{UserID: user.ID, Status: NotificationStatusPinned}).(*Notification)
|
||||
assert.NoError(t, UpdateNotificationStatuses(user, NotificationStatusUnread, NotificationStatusRead))
|
||||
AssertExistsAndLoadBean(t,
|
||||
&Notification{ID: notfUnread.ID, Status: NotificationStatusRead})
|
||||
AssertExistsAndLoadBean(t,
|
||||
&Notification{ID: notfRead.ID, Status: NotificationStatusRead})
|
||||
AssertExistsAndLoadBean(t,
|
||||
&Notification{ID: notfPinned.ID, Status: NotificationStatusPinned})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -453,7 +453,12 @@ func RemoveOrgUser(orgID, userID int64) error {
|
|||
return err
|
||||
}
|
||||
if t.NumMembers == 1 {
|
||||
return ErrLastOrgOwner{UID: userID}
|
||||
if err := t.GetMembers(); err != nil {
|
||||
return err
|
||||
}
|
||||
if t.Members[0].ID == userID {
|
||||
return ErrLastOrgOwner{UID: userID}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
|
|
@ -67,27 +68,11 @@ type PullRequest struct {
|
|||
BaseBranch string
|
||||
MergeBase string `xorm:"VARCHAR(40)"`
|
||||
|
||||
HasMerged bool `xorm:"INDEX"`
|
||||
MergedCommitID string `xorm:"VARCHAR(40)"`
|
||||
MergerID int64 `xorm:"INDEX"`
|
||||
Merger *User `xorm:"-"`
|
||||
Merged time.Time `xorm:"-"`
|
||||
MergedUnix int64 `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
// BeforeUpdate is invoked from XORM before updating an object of this type.
|
||||
func (pr *PullRequest) BeforeUpdate() {
|
||||
pr.MergedUnix = pr.Merged.Unix()
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
// Note: don't try to get Issue because will end up recursive querying.
|
||||
func (pr *PullRequest) AfterLoad() {
|
||||
if !pr.HasMerged {
|
||||
return
|
||||
}
|
||||
|
||||
pr.Merged = time.Unix(pr.MergedUnix, 0).Local()
|
||||
HasMerged bool `xorm:"INDEX"`
|
||||
MergedCommitID string `xorm:"VARCHAR(40)"`
|
||||
MergerID int64 `xorm:"INDEX"`
|
||||
Merger *User `xorm:"-"`
|
||||
MergedUnix util.TimeStamp `xorm:"updated INDEX"`
|
||||
}
|
||||
|
||||
// Note: don't try to get Issue because will end up recursive querying.
|
||||
|
|
@ -194,8 +179,8 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
|||
Base: apiBaseBranchInfo,
|
||||
Head: apiHeadBranchInfo,
|
||||
MergeBase: pr.MergeBase,
|
||||
Created: &pr.Issue.Created,
|
||||
Updated: &pr.Issue.Updated,
|
||||
Created: pr.Issue.CreatedUnix.AsTimePtr(),
|
||||
Updated: pr.Issue.UpdatedUnix.AsTimePtr(),
|
||||
}
|
||||
|
||||
if pr.Status != PullRequestStatusChecking {
|
||||
|
|
@ -203,7 +188,7 @@ func (pr *PullRequest) APIFormat() *api.PullRequest {
|
|||
apiPullRequest.Mergeable = mergeable
|
||||
}
|
||||
if pr.HasMerged {
|
||||
apiPullRequest.Merged = &pr.Merged
|
||||
apiPullRequest.Merged = pr.MergedUnix.AsTimePtr()
|
||||
apiPullRequest.MergedCommitID = &pr.MergedCommitID
|
||||
apiPullRequest.MergedBy = pr.Merger.APIFormat()
|
||||
}
|
||||
|
|
@ -330,7 +315,7 @@ func (pr *PullRequest) Merge(doer *User, baseGitRepo *git.Repository) (err error
|
|||
return fmt.Errorf("GetBranchCommit: %v", err)
|
||||
}
|
||||
|
||||
pr.Merged = time.Now()
|
||||
pr.MergedUnix = util.TimeStampNow()
|
||||
pr.Merger = doer
|
||||
pr.MergerID = doer.ID
|
||||
|
||||
|
|
@ -396,7 +381,7 @@ func (pr *PullRequest) setMerged() (err error) {
|
|||
if pr.HasMerged {
|
||||
return fmt.Errorf("PullRequest[%d] already merged", pr.Index)
|
||||
}
|
||||
if pr.MergedCommitID == "" || pr.Merged.IsZero() || pr.Merger == nil {
|
||||
if pr.MergedCommitID == "" || pr.MergedUnix == 0 || pr.Merger == nil {
|
||||
return fmt.Errorf("Unable to merge PullRequest[%d], some required fields are empty", pr.Index)
|
||||
}
|
||||
|
||||
|
|
@ -442,7 +427,7 @@ func (pr *PullRequest) manuallyMerged() bool {
|
|||
}
|
||||
if commit != nil {
|
||||
pr.MergedCommitID = commit.ID.String()
|
||||
pr.Merged = commit.Author.When
|
||||
pr.MergedUnix = util.TimeStamp(commit.Author.When.Unix())
|
||||
pr.Status = PullRequestStatusManuallyMerged
|
||||
merger, _ := GetUserByEmail(commit.Author.Email)
|
||||
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import (
|
|||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
"github.com/go-xorm/builder"
|
||||
)
|
||||
|
|
@ -30,28 +30,13 @@ type Release struct {
|
|||
Title string
|
||||
Sha1 string `xorm:"VARCHAR(40)"`
|
||||
NumCommits int64
|
||||
NumCommitsBehind int64 `xorm:"-"`
|
||||
Note string `xorm:"TEXT"`
|
||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||
|
||||
Attachments []*Attachment `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX"`
|
||||
}
|
||||
|
||||
// BeforeInsert is invoked from XORM before inserting an object of this type.
|
||||
func (r *Release) BeforeInsert() {
|
||||
if r.CreatedUnix == 0 {
|
||||
r.CreatedUnix = time.Now().Unix()
|
||||
}
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (r *Release) AfterLoad() {
|
||||
r.Created = time.Unix(r.CreatedUnix, 0).Local()
|
||||
NumCommitsBehind int64 `xorm:"-"`
|
||||
Note string `xorm:"TEXT"`
|
||||
IsDraft bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsPrerelease bool `xorm:"NOT NULL DEFAULT false"`
|
||||
IsTag bool `xorm:"NOT NULL DEFAULT false"`
|
||||
Attachments []*Attachment `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created INDEX"`
|
||||
}
|
||||
|
||||
func (r *Release) loadAttributes(e Engine) error {
|
||||
|
|
@ -104,8 +89,8 @@ func (r *Release) APIFormat() *api.Release {
|
|||
ZipURL: r.ZipURL(),
|
||||
IsDraft: r.IsDraft,
|
||||
IsPrerelease: r.IsPrerelease,
|
||||
CreatedAt: r.Created,
|
||||
PublishedAt: r.Created,
|
||||
CreatedAt: r.CreatedUnix.AsTime(),
|
||||
PublishedAt: r.CreatedUnix.AsTime(),
|
||||
Publisher: r.Publisher.APIFormat(),
|
||||
}
|
||||
}
|
||||
|
|
@ -144,7 +129,7 @@ func createTag(gitRepo *git.Repository, rel *Release) error {
|
|||
}
|
||||
|
||||
rel.Sha1 = commit.ID.String()
|
||||
rel.CreatedUnix = commit.Author.When.Unix()
|
||||
rel.CreatedUnix = util.TimeStamp(commit.Author.When.Unix())
|
||||
rel.NumCommits, err = commit.CommitsCount()
|
||||
if err != nil {
|
||||
return fmt.Errorf("CommitsCount: %v", err)
|
||||
|
|
@ -345,7 +330,7 @@ func (rs *releaseSorter) Less(i, j int) bool {
|
|||
if diffNum != 0 {
|
||||
return diffNum > 0
|
||||
}
|
||||
return rs.rels[i].Created.After(rs.rels[j].Created)
|
||||
return rs.rels[i].CreatedUnix > rs.rels[j].CreatedUnix
|
||||
}
|
||||
|
||||
func (rs *releaseSorter) Swap(i, j int) {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/Unknwon/cae/zip"
|
||||
|
|
@ -211,10 +212,8 @@ type Repository struct {
|
|||
Size int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||
IndexerStatus *RepoIndexerStatus `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
|
|
@ -227,8 +226,6 @@ func (repo *Repository) AfterLoad() {
|
|||
repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues
|
||||
repo.NumOpenPulls = repo.NumPulls - repo.NumClosedPulls
|
||||
repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones
|
||||
repo.Created = time.Unix(repo.CreatedUnix, 0).Local()
|
||||
repo.Updated = time.Unix(repo.UpdatedUnix, 0)
|
||||
}
|
||||
|
||||
// MustOwner always returns a valid *User object to avoid
|
||||
|
|
@ -309,8 +306,8 @@ func (repo *Repository) innerAPIFormat(mode AccessMode, isParent bool) *api.Repo
|
|||
Watchers: repo.NumWatches,
|
||||
OpenIssues: repo.NumOpenIssues,
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
Created: repo.Created,
|
||||
Updated: repo.Updated,
|
||||
Created: repo.CreatedUnix.AsTime(),
|
||||
Updated: repo.UpdatedUnix.AsTime(),
|
||||
Permissions: permission,
|
||||
}
|
||||
}
|
||||
|
|
@ -757,12 +754,17 @@ func (repo *Repository) DescriptionHTML() template.HTML {
|
|||
return template.HTML(descPattern.ReplaceAllStringFunc(markup.Sanitize(repo.Description), sanitize))
|
||||
}
|
||||
|
||||
// LocalCopyPath returns the local repository copy path
|
||||
func (repo *Repository) LocalCopyPath() string {
|
||||
// LocalCopyPath returns the local repository copy path.
|
||||
func LocalCopyPath() string {
|
||||
if filepath.IsAbs(setting.Repository.Local.LocalCopyPath) {
|
||||
return path.Join(setting.Repository.Local.LocalCopyPath, com.ToStr(repo.ID))
|
||||
return setting.Repository.Local.LocalCopyPath
|
||||
}
|
||||
return path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath, com.ToStr(repo.ID))
|
||||
return path.Join(setting.AppDataPath, setting.Repository.Local.LocalCopyPath)
|
||||
}
|
||||
|
||||
// LocalCopyPath returns the local repository copy path for the given repo.
|
||||
func (repo *Repository) LocalCopyPath() string {
|
||||
return path.Join(LocalCopyPath(), com.ToStr(repo.ID))
|
||||
}
|
||||
|
||||
// UpdateLocalCopyBranch pulls latest changes of given branch from repoPath to localPath.
|
||||
|
|
@ -1006,10 +1008,10 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
|
|||
|
||||
if opts.IsMirror {
|
||||
if _, err = x.InsertOne(&Mirror{
|
||||
RepoID: repo.ID,
|
||||
Interval: setting.Mirror.DefaultInterval,
|
||||
EnablePrune: true,
|
||||
NextUpdate: time.Now().Add(setting.Mirror.DefaultInterval),
|
||||
RepoID: repo.ID,
|
||||
Interval: setting.Mirror.DefaultInterval,
|
||||
EnablePrune: true,
|
||||
NextUpdateUnix: util.TimeStampNow().AddDuration(setting.Mirror.DefaultInterval),
|
||||
}); err != nil {
|
||||
return repo, fmt.Errorf("InsertOne: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -100,10 +100,6 @@ func populateRepoIndexer() error {
|
|||
}
|
||||
}
|
||||
|
||||
type updateBatch struct {
|
||||
updates []indexer.RepoIndexerUpdate
|
||||
}
|
||||
|
||||
func updateRepoIndexer(repo *Repository) error {
|
||||
changes, err := getRepoChanges(repo)
|
||||
if err != nil {
|
||||
|
|
@ -163,6 +159,10 @@ func addUpdate(filename string, repo *Repository, batch *indexer.Batch) error {
|
|||
return err
|
||||
} else if stat.Size() > setting.Indexer.MaxIndexerFileSize {
|
||||
return nil
|
||||
} else if stat.IsDir() {
|
||||
// file could actually be a directory, if it is the root of a submodule.
|
||||
// We do not index submodule contents, so don't do anything.
|
||||
return nil
|
||||
}
|
||||
fileContents, err := ioutil.ReadFile(filepath)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -31,10 +31,8 @@ type Mirror struct {
|
|||
Interval time.Duration
|
||||
EnablePrune bool `xorm:"NOT NULL DEFAULT true"`
|
||||
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX"`
|
||||
NextUpdate time.Time `xorm:"-"`
|
||||
NextUpdateUnix int64 `xorm:"INDEX"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX"`
|
||||
NextUpdateUnix util.TimeStamp `xorm:"INDEX"`
|
||||
|
||||
address string `xorm:"-"`
|
||||
}
|
||||
|
|
@ -42,16 +40,8 @@ type Mirror struct {
|
|||
// BeforeInsert will be invoked by XORM before inserting a record
|
||||
func (m *Mirror) BeforeInsert() {
|
||||
if m != nil {
|
||||
m.UpdatedUnix = time.Now().Unix()
|
||||
m.NextUpdateUnix = m.NextUpdate.Unix()
|
||||
}
|
||||
}
|
||||
|
||||
// BeforeUpdate is invoked from XORM before updating this object.
|
||||
func (m *Mirror) BeforeUpdate() {
|
||||
if m != nil {
|
||||
m.UpdatedUnix = m.Updated.Unix()
|
||||
m.NextUpdateUnix = m.NextUpdate.Unix()
|
||||
m.UpdatedUnix = util.TimeStampNow()
|
||||
m.NextUpdateUnix = util.TimeStampNow()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -66,14 +56,11 @@ func (m *Mirror) AfterLoad(session *xorm.Session) {
|
|||
if err != nil {
|
||||
log.Error(3, "getRepositoryByID[%d]: %v", m.ID, err)
|
||||
}
|
||||
|
||||
m.Updated = time.Unix(m.UpdatedUnix, 0).Local()
|
||||
m.NextUpdate = time.Unix(m.NextUpdateUnix, 0).Local()
|
||||
}
|
||||
|
||||
// ScheduleNextUpdate calculates and sets next update time.
|
||||
func (m *Mirror) ScheduleNextUpdate() {
|
||||
m.NextUpdate = time.Now().Add(m.Interval)
|
||||
m.NextUpdateUnix = util.TimeStampNow().AddDuration(m.Interval)
|
||||
}
|
||||
|
||||
func remoteAddress(repoPath string) (string, error) {
|
||||
|
|
@ -193,7 +180,7 @@ func (m *Mirror) runSync() bool {
|
|||
}
|
||||
}
|
||||
|
||||
m.Updated = time.Now()
|
||||
m.UpdatedUnix = util.TimeStampNow()
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,8 @@ package models
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/core"
|
||||
|
|
@ -19,8 +20,7 @@ type RepoUnit struct {
|
|||
RepoID int64 `xorm:"INDEX(s)"`
|
||||
Type UnitType `xorm:"INDEX(s)"`
|
||||
Config core.Conversion `xorm:"TEXT"`
|
||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX CREATED"`
|
||||
}
|
||||
|
||||
// UnitConfig describes common unit config
|
||||
|
|
@ -106,11 +106,6 @@ func (r *RepoUnit) BeforeSet(colName string, val xorm.Cell) {
|
|||
}
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (r *RepoUnit) AfterLoad() {
|
||||
r.Created = time.Unix(r.CreatedUnix, 0).Local()
|
||||
}
|
||||
|
||||
// Unit returns Unit
|
||||
func (r *RepoUnit) Unit() Unit {
|
||||
return Units[r.Type]
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/process"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -54,20 +55,16 @@ type PublicKey struct {
|
|||
Mode AccessMode `xorm:"NOT NULL DEFAULT 2"`
|
||||
Type KeyType `xorm:"NOT NULL DEFAULT 1"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (key *PublicKey) AfterLoad() {
|
||||
key.Created = time.Unix(key.CreatedUnix, 0).Local()
|
||||
key.Updated = time.Unix(key.UpdatedUnix, 0).Local()
|
||||
key.HasUsed = key.Updated.After(key.Created)
|
||||
key.HasRecentActivity = key.Updated.Add(7 * 24 * time.Hour).After(time.Now())
|
||||
key.HasUsed = key.UpdatedUnix > key.CreatedUnix
|
||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow()
|
||||
}
|
||||
|
||||
// OmitEmail returns content of public key without email address.
|
||||
|
|
@ -484,7 +481,7 @@ func UpdatePublicKeyUpdated(id int64) error {
|
|||
}
|
||||
|
||||
_, err := x.ID(id).Cols("updated_unix").Update(&PublicKey{
|
||||
UpdatedUnix: time.Now().Unix(),
|
||||
UpdatedUnix: util.TimeStampNow(),
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -603,20 +600,16 @@ type DeployKey struct {
|
|||
Fingerprint string
|
||||
Content string `xorm:"-"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (key *DeployKey) AfterLoad() {
|
||||
key.Created = time.Unix(key.CreatedUnix, 0).Local()
|
||||
key.Updated = time.Unix(key.UpdatedUnix, 0).Local()
|
||||
key.HasUsed = key.Updated.After(key.Created)
|
||||
key.HasRecentActivity = key.Updated.Add(7 * 24 * time.Hour).After(time.Now())
|
||||
key.HasUsed = key.UpdatedUnix > key.CreatedUnix
|
||||
key.HasRecentActivity = key.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow()
|
||||
}
|
||||
|
||||
// GetContent gets associated public key content.
|
||||
|
|
@ -743,6 +736,12 @@ func GetDeployKeyByRepo(keyID, repoID int64) (*DeployKey, error) {
|
|||
return key, nil
|
||||
}
|
||||
|
||||
// UpdateDeployKeyCols updates deploy key information in the specified columns.
|
||||
func UpdateDeployKeyCols(key *DeployKey, cols ...string) error {
|
||||
_, err := x.ID(key.ID).Cols(cols...).Update(key)
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateDeployKey updates deploy key information.
|
||||
func UpdateDeployKey(key *DeployKey) error {
|
||||
_, err := x.ID(key.ID).AllCols().Update(key)
|
||||
|
|
|
|||
|
|
@ -8,11 +8,11 @@ import (
|
|||
"container/list"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
"github.com/go-xorm/xorm"
|
||||
|
|
@ -65,17 +65,8 @@ type CommitStatus struct {
|
|||
Creator *User `xorm:"-"`
|
||||
CreatorID int64
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the value of a field of
|
||||
// this object.
|
||||
func (status *CommitStatus) AfterLoad() {
|
||||
status.Created = time.Unix(status.CreatedUnix, 0).Local()
|
||||
status.Updated = time.Unix(status.UpdatedUnix, 0).Local()
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
func (status *CommitStatus) loadRepo(e Engine) (err error) {
|
||||
|
|
@ -106,8 +97,8 @@ func (status *CommitStatus) APIURL() string {
|
|||
func (status *CommitStatus) APIFormat() *api.Status {
|
||||
status.loadRepo(x)
|
||||
apiStatus := &api.Status{
|
||||
Created: status.Created,
|
||||
Updated: status.Created,
|
||||
Created: status.CreatedUnix.AsTime(),
|
||||
Updated: status.CreatedUnix.AsTime(),
|
||||
State: api.StatusState(status.State),
|
||||
TargetURL: status.TargetURL,
|
||||
Description: status.Description,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import (
|
|||
gouuid "github.com/satori/go.uuid"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// AccessToken represents a personal access token.
|
||||
|
|
@ -19,20 +20,16 @@ type AccessToken struct {
|
|||
Name string
|
||||
Sha1 string `xorm:"UNIQUE VARCHAR(40)"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
HasRecentActivity bool `xorm:"-"`
|
||||
HasUsed bool `xorm:"-"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (t *AccessToken) AfterLoad() {
|
||||
t.Created = time.Unix(t.CreatedUnix, 0).Local()
|
||||
t.Updated = time.Unix(t.UpdatedUnix, 0).Local()
|
||||
t.HasUsed = t.Updated.After(t.Created)
|
||||
t.HasRecentActivity = t.Updated.Add(7 * 24 * time.Hour).After(time.Now())
|
||||
t.HasUsed = t.UpdatedUnix > t.CreatedUnix
|
||||
t.HasRecentActivity = t.UpdatedUnix.AddDuration(7*24*time.Hour) > util.TimeStampNow()
|
||||
}
|
||||
|
||||
// NewAccessToken creates new access token.
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import (
|
|||
"crypto/md5"
|
||||
"crypto/subtle"
|
||||
"encoding/base64"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/pquerna/otp/totp"
|
||||
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// TwoFactor represents a two-factor authentication token.
|
||||
|
|
@ -23,17 +23,8 @@ type TwoFactor struct {
|
|||
UID int64 `xorm:"UNIQUE"`
|
||||
Secret string
|
||||
ScratchToken string
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (t *TwoFactor) AfterLoad() {
|
||||
t.Created = time.Unix(t.CreatedUnix, 0).Local()
|
||||
t.Updated = time.Unix(t.UpdatedUnix, 0).Local()
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// GenerateScratchToken recreates the scratch token the user is using.
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ import (
|
|||
"github.com/Unknwon/com"
|
||||
"github.com/go-xorm/core"
|
||||
"github.com/go-xorm/xorm"
|
||||
_ "github.com/mattn/go-sqlite3" // for the test engine
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/testfixtures.v2"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// NonexistentID an ID that will never exist
|
||||
|
|
@ -29,9 +29,10 @@ var giteaRoot string
|
|||
// MainTest a reusable TestMain(..) function for unit tests that need to use a
|
||||
// test database. Creates the test database, and sets necessary settings.
|
||||
func MainTest(m *testing.M, pathToGiteaRoot string) {
|
||||
var err error
|
||||
giteaRoot = pathToGiteaRoot
|
||||
fixturesDir := filepath.Join(pathToGiteaRoot, "models", "fixtures")
|
||||
if err := createTestEngine(fixturesDir); err != nil {
|
||||
if err = createTestEngine(fixturesDir); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error creating test engine: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -42,6 +43,13 @@ func MainTest(m *testing.M, pathToGiteaRoot string) {
|
|||
setting.SSH.Domain = "try.gitea.io"
|
||||
setting.RepoRootPath = filepath.Join(os.TempDir(), "repos")
|
||||
setting.AppDataPath = filepath.Join(os.TempDir(), "appdata")
|
||||
setting.AppWorkPath = pathToGiteaRoot
|
||||
setting.StaticRootPath = pathToGiteaRoot
|
||||
setting.GravatarSourceURL, err = url.Parse("https://secure.gravatar.com/avatar/")
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Error url.Parse: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
os.Exit(m.Run())
|
||||
}
|
||||
|
|
@ -141,6 +149,14 @@ func AssertNotExistsBean(t *testing.T, bean interface{}, conditions ...interface
|
|||
assert.False(t, exists)
|
||||
}
|
||||
|
||||
// AssertExistsIf asserts that a bean exists or does not exist, depending on
|
||||
// what is expected.
|
||||
func AssertExistsIf(t *testing.T, expected bool, bean interface{}, conditions ...interface{}) {
|
||||
exists, err := loadBeanIfExists(bean, conditions...)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expected, exists)
|
||||
}
|
||||
|
||||
// AssertSuccessfulInsert assert that beans is successfully inserted
|
||||
func AssertSuccessfulInsert(t *testing.T, beans ...interface{}) {
|
||||
_, err := x.Insert(beans...)
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import (
|
|||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/modules/cache"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
)
|
||||
|
||||
// env keys for git hooks need
|
||||
|
|
@ -158,8 +159,7 @@ func pushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string)
|
|||
IsDraft: false,
|
||||
IsPrerelease: false,
|
||||
IsTag: true,
|
||||
Created: createdAt,
|
||||
CreatedUnix: createdAt.Unix(),
|
||||
CreatedUnix: util.TimeStamp(createdAt.Unix()),
|
||||
}
|
||||
if author != nil {
|
||||
rel.PublisherID = author.ID
|
||||
|
|
@ -170,8 +170,7 @@ func pushUpdateAddTag(repo *Repository, gitRepo *git.Repository, tagName string)
|
|||
}
|
||||
} else {
|
||||
rel.Sha1 = commit.ID.String()
|
||||
rel.Created = createdAt
|
||||
rel.CreatedUnix = createdAt.Unix()
|
||||
rel.CreatedUnix = util.TimeStamp(createdAt.Unix())
|
||||
rel.NumCommits = commitsCount
|
||||
rel.IsDraft = false
|
||||
if rel.IsTag && author != nil {
|
||||
|
|
|
|||
|
|
@ -94,12 +94,9 @@ type User struct {
|
|||
Rands string `xorm:"VARCHAR(10)"`
|
||||
Salt string `xorm:"VARCHAR(10)"`
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
LastLogin time.Time `xorm:"-"`
|
||||
LastLoginUnix int64 `xorm:"INDEX"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
LastLoginUnix util.TimeStamp `xorm:"INDEX"`
|
||||
|
||||
// Remember visibility choice for convenience, true for private
|
||||
LastRepoVisibility bool
|
||||
|
|
@ -145,7 +142,7 @@ func (u *User) BeforeUpdate() {
|
|||
|
||||
// SetLastLogin set time to last login
|
||||
func (u *User) SetLastLogin() {
|
||||
u.LastLoginUnix = time.Now().Unix()
|
||||
u.LastLoginUnix = util.TimeStampNow()
|
||||
}
|
||||
|
||||
// UpdateDiffViewStyle updates the users diff view style
|
||||
|
|
@ -154,13 +151,6 @@ func (u *User) UpdateDiffViewStyle(style string) error {
|
|||
return UpdateUserCols(u, "diff_view_style")
|
||||
}
|
||||
|
||||
// AfterLoad is invoked from XORM after setting the values of all fields of this object.
|
||||
func (u *User) AfterLoad() {
|
||||
u.Created = time.Unix(u.CreatedUnix, 0).Local()
|
||||
u.Updated = time.Unix(u.UpdatedUnix, 0).Local()
|
||||
u.LastLogin = time.Unix(u.LastLoginUnix, 0).Local()
|
||||
}
|
||||
|
||||
// getEmail returns an noreply email, if the user has set to keep his
|
||||
// email address private, otherwise the primary email address.
|
||||
func (u *User) getEmail() string {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/sync"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
api "code.gitea.io/sdk/gitea"
|
||||
|
||||
gouuid "github.com/satori/go.uuid"
|
||||
|
|
@ -105,10 +106,8 @@ type Webhook struct {
|
|||
Meta string `xorm:"TEXT"` // store hook-specific attributes
|
||||
LastStatus HookStatus // Last delivery status
|
||||
|
||||
Created time.Time `xorm:"-"`
|
||||
CreatedUnix int64 `xorm:"INDEX created"`
|
||||
Updated time.Time `xorm:"-"`
|
||||
UpdatedUnix int64 `xorm:"INDEX updated"`
|
||||
CreatedUnix util.TimeStamp `xorm:"INDEX created"`
|
||||
UpdatedUnix util.TimeStamp `xorm:"INDEX updated"`
|
||||
}
|
||||
|
||||
// AfterLoad updates the webhook object upon setting a column
|
||||
|
|
@ -117,9 +116,6 @@ func (w *Webhook) AfterLoad() {
|
|||
if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
|
||||
log.Error(3, "Unmarshal[%d]: %v", w.ID, err)
|
||||
}
|
||||
|
||||
w.Created = time.Unix(w.CreatedUnix, 0).Local()
|
||||
w.Updated = time.Unix(w.UpdatedUnix, 0).Local()
|
||||
}
|
||||
|
||||
// GetSlackHook returns slack metadata
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ package auth
|
|||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/go-macaron/binding"
|
||||
|
|
@ -19,6 +18,7 @@ import (
|
|||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"code.gitea.io/gitea/modules/validation"
|
||||
)
|
||||
|
||||
|
|
@ -59,7 +59,7 @@ func SignedInID(ctx *macaron.Context, sess session.Store) int64 {
|
|||
}
|
||||
return 0
|
||||
}
|
||||
t.Updated = time.Now()
|
||||
t.UpdatedUnix = util.TimeStampNow()
|
||||
if err = models.UpdateAccessToken(t); err != nil {
|
||||
log.Error(4, "UpdateAccessToken: %v", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
"code.gitea.io/gitea/modules/util"
|
||||
"github.com/Unknwon/com"
|
||||
"github.com/Unknwon/i18n"
|
||||
"github.com/gogits/chardet"
|
||||
|
|
@ -357,11 +358,15 @@ func timeSincePro(then, now time.Time, lang string) string {
|
|||
}
|
||||
|
||||
func timeSince(then, now time.Time, lang string) string {
|
||||
return timeSinceUnix(then.Unix(), now.Unix(), lang)
|
||||
}
|
||||
|
||||
func timeSinceUnix(then, now int64, lang string) string {
|
||||
lbl := "tool.ago"
|
||||
diff := now.Unix() - then.Unix()
|
||||
if then.After(now) {
|
||||
diff := now - then
|
||||
if then > now {
|
||||
lbl = "tool.from_now"
|
||||
diff = then.Unix() - now.Unix()
|
||||
diff = then - now
|
||||
}
|
||||
if diff <= 0 {
|
||||
return i18n.Tr(lang, "tool.now")
|
||||
|
|
@ -387,6 +392,17 @@ func htmlTimeSince(then, now time.Time, lang string) template.HTML {
|
|||
timeSince(then, now, lang)))
|
||||
}
|
||||
|
||||
// TimeSinceUnix calculates the time interval and generate user-friendly string.
|
||||
func TimeSinceUnix(then util.TimeStamp, lang string) template.HTML {
|
||||
return htmlTimeSinceUnix(then, util.TimeStamp(time.Now().Unix()), lang)
|
||||
}
|
||||
|
||||
func htmlTimeSinceUnix(then, now util.TimeStamp, lang string) template.HTML {
|
||||
return template.HTML(fmt.Sprintf(`<span class="time-since" title="%s">%s</span>`,
|
||||
then.Format(setting.TimeFormat),
|
||||
timeSinceUnix(int64(then), int64(now), lang)))
|
||||
}
|
||||
|
||||
// Storage space size types
|
||||
const (
|
||||
Byte = 1
|
||||
|
|
|
|||
|
|
@ -435,7 +435,6 @@ func RepoAssignment() macaron.Handler {
|
|||
return
|
||||
}
|
||||
}
|
||||
ctx.Data["IsForkedRepo"] = repo.IsFork
|
||||
|
||||
// People who have push access or have forked repository can propose a new pull request.
|
||||
if ctx.Repo.IsWriter() || (ctx.IsSigned && ctx.User.HasForkedRepo(ctx.Repo.Repository.ID)) {
|
||||
|
|
@ -626,7 +625,11 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
|
|||
|
||||
if refType == RepoRefLegacy {
|
||||
// redirect from old URL scheme to new URL scheme
|
||||
ctx.Redirect(path.Join(setting.AppSubURL, strings.TrimSuffix(ctx.Req.URL.String(), ctx.Params("*")), ctx.Repo.BranchNameSubURL()))
|
||||
ctx.Redirect(path.Join(
|
||||
setting.AppSubURL,
|
||||
strings.TrimSuffix(ctx.Req.URL.String(), ctx.Params("*")),
|
||||
ctx.Repo.BranchNameSubURL(),
|
||||
ctx.Repo.TreePath))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,12 +68,12 @@ type ObjectError struct {
|
|||
|
||||
// ObjectLink builds a URL linking to the object.
|
||||
func (v *RequestVars) ObjectLink() string {
|
||||
return setting.AppURL + path.Join(v.User, v.Repo, "info/lfs/objects", v.Oid)
|
||||
return setting.AppURL + path.Join(v.User, v.Repo+".git", "info/lfs/objects", v.Oid)
|
||||
}
|
||||
|
||||
// VerifyLink builds a URL for verifying the object.
|
||||
func (v *RequestVars) VerifyLink() string {
|
||||
return setting.AppURL + path.Join(v.User, v.Repo, "info/lfs/verify")
|
||||
return setting.AppURL + path.Join(v.User, v.Repo+".git", "info/lfs/verify")
|
||||
}
|
||||
|
||||
// link provides a structure used to build a hypermedia representation of an HTTP link.
|
||||
|
|
|
|||
|
|
@ -531,6 +531,9 @@ var (
|
|||
IterateBufferSize int
|
||||
|
||||
ExternalMarkupParsers []MarkupParser
|
||||
// UILocation is the location on the UI, so that we can display the time on UI.
|
||||
// Currently only show the default time.Local, it could be added to app.ini after UI is ready
|
||||
UILocation = time.Local
|
||||
)
|
||||
|
||||
// DateLang transforms standard language locale name to corresponding value in datetime plugin.
|
||||
|
|
|
|||
|
|
@ -65,14 +65,15 @@ func NewFuncMap() []template.FuncMap {
|
|||
"LoadTimes": func(startTime time.Time) string {
|
||||
return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms"
|
||||
},
|
||||
"AvatarLink": base.AvatarLink,
|
||||
"Safe": Safe,
|
||||
"SafeJS": SafeJS,
|
||||
"Str2html": Str2html,
|
||||
"TimeSince": base.TimeSince,
|
||||
"RawTimeSince": base.RawTimeSince,
|
||||
"FileSize": base.FileSize,
|
||||
"Subtract": base.Subtract,
|
||||
"AvatarLink": base.AvatarLink,
|
||||
"Safe": Safe,
|
||||
"SafeJS": SafeJS,
|
||||
"Str2html": Str2html,
|
||||
"TimeSince": base.TimeSince,
|
||||
"TimeSinceUnix": base.TimeSinceUnix,
|
||||
"RawTimeSince": base.RawTimeSince,
|
||||
"FileSize": base.FileSize,
|
||||
"Subtract": base.Subtract,
|
||||
"Add": func(a, b int) int {
|
||||
return a + b
|
||||
},
|
||||
|
|
|
|||
|
|
@ -9,13 +9,14 @@ import (
|
|||
"net/url"
|
||||
"testing"
|
||||
|
||||
"code.gitea.io/git"
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/modules/context"
|
||||
|
||||
"github.com/go-macaron/session"
|
||||
_ "github.com/mattn/go-sqlite3" // for the test engine
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/macaron.v1"
|
||||
"net/http/httptest"
|
||||
)
|
||||
|
||||
// MockContext mock context for unit tests
|
||||
|
|
@ -44,6 +45,7 @@ func MockContext(t *testing.T, path string) *context.Context {
|
|||
func LoadRepo(t *testing.T, ctx *context.Context, repoID int64) {
|
||||
ctx.Repo = &context.Repository{}
|
||||
ctx.Repo.Repository = models.AssertExistsAndLoadBean(t, &models.Repository{ID: repoID}).(*models.Repository)
|
||||
ctx.Repo.RepoLink = ctx.Repo.Repository.Link()
|
||||
}
|
||||
|
||||
// LoadUser load a user into a test context.
|
||||
|
|
@ -51,6 +53,15 @@ func LoadUser(t *testing.T, ctx *context.Context, userID int64) {
|
|||
ctx.User = models.AssertExistsAndLoadBean(t, &models.User{ID: userID}).(*models.User)
|
||||
}
|
||||
|
||||
// LoadGitRepo load a git repo into a test context. Requires that ctx.Repo has
|
||||
// already been populated.
|
||||
func LoadGitRepo(t *testing.T, ctx *context.Context) {
|
||||
assert.NoError(t, ctx.Repo.Repository.GetOwner())
|
||||
var err error
|
||||
ctx.Repo.GitRepo, err = git.OpenRepository(ctx.Repo.Repository.RepoPath())
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
type mockLocale struct{}
|
||||
|
||||
func (l mockLocale) Language() string {
|
||||
|
|
@ -62,32 +73,21 @@ func (l mockLocale) Tr(s string, _ ...interface{}) string {
|
|||
}
|
||||
|
||||
type mockResponseWriter struct {
|
||||
status int
|
||||
size int
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Header() http.Header {
|
||||
return map[string][]string{}
|
||||
httptest.ResponseRecorder
|
||||
size int
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Write(b []byte) (int, error) {
|
||||
rw.size += len(b)
|
||||
return len(b), nil
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) WriteHeader(status int) {
|
||||
rw.status = status
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Flush() {
|
||||
return rw.ResponseRecorder.Write(b)
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Status() int {
|
||||
return rw.status
|
||||
return rw.ResponseRecorder.Code
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Written() bool {
|
||||
return rw.status > 0
|
||||
return rw.ResponseRecorder.Code > 0
|
||||
}
|
||||
|
||||
func (rw *mockResponseWriter) Size() int {
|
||||
|
|
|
|||
14
modules/test/utils.go
Normal file
14
modules/test/utils.go
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2017 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 test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
// RedirectURL returns the redirect URL of a http response.
|
||||
func RedirectURL(resp http.ResponseWriter) string {
|
||||
return resp.Header().Get("Location")
|
||||
}
|
||||
61
modules/util/time_stamp.go
Normal file
61
modules/util/time_stamp.go
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
// Copyright 2017 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 util
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
)
|
||||
|
||||
// TimeStamp defines a timestamp
|
||||
type TimeStamp int64
|
||||
|
||||
// TimeStampNow returns now int64
|
||||
func TimeStampNow() TimeStamp {
|
||||
return TimeStamp(time.Now().Unix())
|
||||
}
|
||||
|
||||
// Add adds seconds and return sum
|
||||
func (ts TimeStamp) Add(seconds int64) TimeStamp {
|
||||
return ts + TimeStamp(seconds)
|
||||
}
|
||||
|
||||
// AddDuration adds time.Duration and return sum
|
||||
func (ts TimeStamp) AddDuration(interval time.Duration) TimeStamp {
|
||||
return ts + TimeStamp(interval/time.Second)
|
||||
}
|
||||
|
||||
// Year returns the time's year
|
||||
func (ts TimeStamp) Year() int {
|
||||
return ts.AsTime().Year()
|
||||
}
|
||||
|
||||
// AsTime convert timestamp as time.Time in Local locale
|
||||
func (ts TimeStamp) AsTime() (tm time.Time) {
|
||||
tm = time.Unix(int64(ts), 0).In(setting.UILocation)
|
||||
return
|
||||
}
|
||||
|
||||
// AsTimePtr convert timestamp as *time.Time in Local locale
|
||||
func (ts TimeStamp) AsTimePtr() *time.Time {
|
||||
tm := time.Unix(int64(ts), 0).In(setting.UILocation)
|
||||
return &tm
|
||||
}
|
||||
|
||||
// Format formats timestamp as
|
||||
func (ts TimeStamp) Format(f string) string {
|
||||
return ts.AsTime().Format(f)
|
||||
}
|
||||
|
||||
// FormatLong formats as RFC1123Z
|
||||
func (ts TimeStamp) FormatLong() string {
|
||||
return ts.Format(time.RFC1123Z)
|
||||
}
|
||||
|
||||
// FormatShort formats as short
|
||||
func (ts TimeStamp) FormatShort() string {
|
||||
return ts.Format("Jan 02, 2006")
|
||||
}
|
||||
|
|
@ -1569,6 +1569,7 @@ no_read = You do not have any read notifications.
|
|||
pin = Pin notification
|
||||
mark_as_read = Mark as read
|
||||
mark_as_unread = Mark as unread
|
||||
mark_all_as_read = Mark all as read
|
||||
|
||||
[gpg]
|
||||
error.extract_sign = Failed to extract signature
|
||||
|
|
|
|||
|
|
@ -489,6 +489,8 @@ mirror_last_synced=Dernière synchronisation
|
|||
watchers=Observateurs
|
||||
stargazers=Fans
|
||||
forks=Bifurcations
|
||||
pick_reaction=Choisissez votre réaction
|
||||
reactions_more=et %d de plus
|
||||
|
||||
form.reach_limit_of_creation=Vous avez déjà atteint la limite des %d dépôts.
|
||||
form.name_reserved=Le dépôt "%s" a un nom réservé.
|
||||
|
|
@ -539,6 +541,7 @@ pulls=Demandes d'ajout
|
|||
labels=Étiquettes
|
||||
milestones=Jalons
|
||||
commits=Révisions
|
||||
commit=Commit
|
||||
releases=Versions
|
||||
file_raw=Brut
|
||||
file_history=Historique
|
||||
|
|
@ -804,6 +807,7 @@ wiki.new_page_button=Nouvelle Page
|
|||
wiki.delete_page_button=Supprimer la page
|
||||
wiki.delete_page_notice_1=Cela supprimera la page <code>"%s"</code>. Êtes-vous sûr ?
|
||||
wiki.page_already_exists=Une page de wiki avec le même nom existe déjà.
|
||||
wiki.reserved_page=Le nom de page Wiki %s est réservé, veuillez choisir un autre nom.
|
||||
wiki.pages=Pages
|
||||
wiki.last_updated=Dernière mise à jour: %s
|
||||
|
||||
|
|
@ -978,6 +982,7 @@ settings.slack_token=Jeton
|
|||
settings.slack_domain=Domaine
|
||||
settings.slack_channel=Canal
|
||||
settings.add_discord_hook_desc=Ajouter l'intégration de <a href="%s">Discord</a> à votre dépôt.
|
||||
settings.add_dingtalk_hook_desc=Intégrer <a href="%s">Dingtalk</a> à votre dépôt.
|
||||
settings.deploy_keys=Clés de déploiement
|
||||
settings.add_deploy_key=Ajouter une clé de déploiement
|
||||
settings.deploy_key_desc=Les clés de déploiement ont un accès en lecture seule. Elles sont différentes des clés SSH personnelles.
|
||||
|
|
@ -1542,6 +1547,7 @@ no_read=Vous n'avez aucune notification lue.
|
|||
pin=Epingler la notification
|
||||
mark_as_read=Marquer comme lu
|
||||
mark_as_unread=Marquer comme non lue
|
||||
mark_all_as_read=Tout marquer comme lu
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=Impossible d'extraire la signature
|
||||
|
|
|
|||
|
|
@ -1547,6 +1547,7 @@ no_read=Nincsen olvasott értesítés.
|
|||
pin=Értesítés kitűzése
|
||||
mark_as_read=Megjelölés olvasottként
|
||||
mark_as_unread=Megjelölés olvasatlanként
|
||||
mark_all_as_read=Összes üzenet megjelölése olvasottként
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=Nem sikerült kinyerni az aláírást
|
||||
|
|
|
|||
|
|
@ -489,6 +489,8 @@ mirror_last_synced=Pēdējo reizi sinhronizēts
|
|||
watchers=Novērotāji
|
||||
stargazers=Zvaigžņdevēji
|
||||
forks=Atdalītie repozitoriji
|
||||
pick_reaction=Izvēlieties reakciju
|
||||
reactions_more=un vēl %d
|
||||
|
||||
form.reach_limit_of_creation=Ir sasniegts Jums noteiktais %d repozitoriju ierobežojums.
|
||||
form.name_reserved=Repozitorija nosaukums '%s' ir jau rezervēts.
|
||||
|
|
@ -539,6 +541,7 @@ pulls=Izmaiņu pieprasījumi
|
|||
labels=Etiķetes
|
||||
milestones=Atskaites punkti
|
||||
commits=Revīzijas
|
||||
commit=Revīzija
|
||||
releases=Laidieni
|
||||
file_raw=Neapstrādāts
|
||||
file_history=Vēsture
|
||||
|
|
@ -1544,6 +1547,7 @@ no_read=Jums nav neviena izlasīta paziņojuma.
|
|||
pin=Piespraust paziņojumu
|
||||
mark_as_read=Atzīmēt kā izlasītu
|
||||
mark_as_unread=Atzīmēt kā nelasītu
|
||||
mark_all_as_read=Atzīmēt visus kā izlasītus
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=Neizdevās izgūt parakstu
|
||||
|
|
|
|||
|
|
@ -139,7 +139,6 @@ invalid_repo_path=Ścieżka repozytoriów nie jest poprawna: %v
|
|||
run_user_not_match=Użytkownik aplikacji nie jest aktualnym użytkownikiem: %s -> %s
|
||||
save_config_failed=Nie udało się zapisać konfiguracji: %v
|
||||
invalid_admin_setting=Nieprawidłowe ustawienia konta admina: %v
|
||||
install_success=Witaj! Dziękujemy za wybranie Gitea. Miłej zabawy. Trzymaj się!
|
||||
invalid_log_root_path=Ścieżka dla logów jest niepoprawna: %v
|
||||
default_keep_email_private=Domyślnie ukrywaj adresy e-mail
|
||||
default_keep_email_private_popup=To jest domyślne ustawienie widoczności adresu e-mail użytkowników. Włączone spowoduje, że adres e-mail wszystkich nowych użytkowników zostanie domyślnie ukryty.
|
||||
|
|
@ -201,8 +200,6 @@ non_local_account=Nie lokalne konta nie mogą zmieniać haseł przez webowy inte
|
|||
verify=Potwierdź
|
||||
scratch_code=Scratch kod
|
||||
use_scratch_code=Użyj scratch kod
|
||||
twofa_scratch_used=Użyłeś/aś swojego kodu zdrapki. Przekierowano Cię do strony z ustawieniami autoryzacji dwuetapowej, gdzie możesz usunąć usunąć swoje urządzenie lub wygenerować nowy kod zdrapkę.
|
||||
twofa_passcode_incorrect=Twój kod autoryzacji jest niepoprawny. Jeśli zapodziałeś/aś swoje urządzenie, użyj swojego kodu zdrapki do zalogowania.
|
||||
twofa_scratch_token_incorrect=Scratch token nie jest poprawny.
|
||||
login_userpass=Użytkownik / Hasło
|
||||
login_openid=OpenID
|
||||
|
|
@ -434,11 +431,9 @@ twofa_disable_note=W razie potrzeby można wyłączyć uwierzytelnianie dwuetapo
|
|||
twofa_disable_desc=Wyłączenie dwuetapowej autoryzacji sprawi, że Twoje konto będzie mniej bezpieczne. Czy na pewno chcesz kontynuować?
|
||||
regenerate_scratch_token_desc=Jeśli zgubiłeś lub zużyłeś swój scratch token możesz go wygenerować tutaj.
|
||||
twofa_disabled=Dwuetapowa autoryzacja została wyłączona.
|
||||
scan_this_image=Zeskanuj ten obraz za pomocą swojej aplikacji autoryzacyjnej:
|
||||
or_enter_secret=Lub wprowadź sekret: %s
|
||||
then_enter_passcode=I podaj kod autoryzacji otrzymany z aplikacji:
|
||||
passcode_invalid=Kod dostępu jest nieprawidłowy. Spróbuj ponownie.
|
||||
twofa_enrolled=Twoje konto ma teraz włączoną autoryzację dwuetapową. Koniecznie zachowaj swój kod zdrapkę (%s), ponieważ będzie pokazany tylko raz!
|
||||
|
||||
manage_account_links=Zarządzaj połączonymi kontami
|
||||
manage_account_links_desc=Zewnętrzne konta połączone z tym kontem
|
||||
|
|
@ -460,7 +455,6 @@ owner=Właściciel
|
|||
repo_name=Nazwa repozytorium
|
||||
repo_name_helper=Dobra nazwa repozytorium jest utworzona z krótkich, łatwych do zapamiętania i unikalnych słów kluczowych.
|
||||
visibility=Widoczność
|
||||
visiblity_helper=Te repozytorium jest <span class="ui red text">prywatne</span>
|
||||
visiblity_helper_forced=Administrator systemu wymaga, żeby wszystkie nowe repozytoria były <span class="ui red text">prywatne</span>
|
||||
visiblity_fork_helper=(Zmiana tej wartości wpłynie na wszystkie forki)
|
||||
clone_helper=Potrzebujesz pomocy z klonowaniem? Odwiedź <a target="_blank" rel="noopener" href="%s">Pomoc</a>!
|
||||
|
|
@ -494,7 +488,6 @@ form.name_pattern_not_allowed=Wzorzec nazwy repozytorium „%s” jest niedozwol
|
|||
|
||||
need_auth=Wymaga autoryzacji
|
||||
migrate_type=Typ migracji
|
||||
migrate_type_helper=Te repozytorium będzie <span class="text blue">kopią lustrzaną</span>
|
||||
migrate_repo=Przenieś repozytorium
|
||||
migrate.clone_address=Sklonuj adres
|
||||
migrate.clone_address_desc=To może być adres HTTP/HTTPS/GIT lub ścieżka lokalna serwera.
|
||||
|
|
@ -550,7 +543,6 @@ editor.edit_file=Edytuj plik
|
|||
editor.preview_changes=Podgląd zmian
|
||||
editor.cannot_edit_non_text_files=Nie można edytować plików binarnych przez interfejs webowy
|
||||
editor.edit_this_file=Edytuj ten plik
|
||||
editor.must_be_on_a_branch=Musisz być na gałęzi aby zgłosić lub zaproponować zmiany tego pliku
|
||||
editor.fork_before_edit=Musisz sforkować to repozytorium przed edycją tego pliku
|
||||
editor.delete_this_file=Usuń ten plik
|
||||
editor.must_have_write_access=Musisz mieć uprawnienia do zapisu, aby zgłosić lub zaproponować zmiany do tego pliku
|
||||
|
|
@ -1264,7 +1256,6 @@ auths.domain=Domena
|
|||
auths.host=Serwer
|
||||
auths.port=Port
|
||||
auths.bind_password=Hasło Bind
|
||||
auths.bind_password_helper=Uwaga: Te hasło jest przechowywane bez szyfrowania. Zdecydowanie zalecane jest użycie konta z uprawnieniami tylko do odczytu.
|
||||
auths.user_base=Baza wyszukiwania
|
||||
auths.user_dn=DN użytkownika
|
||||
auths.attribute_username=Atrybut nazwy użytkownika
|
||||
|
|
@ -1446,7 +1437,6 @@ notices.type=Typ
|
|||
notices.type_1=Repozytorium
|
||||
notices.desc=Opis
|
||||
notices.op=Operacja
|
||||
notices.delete_success=Powiadomienia systemowe zostały usunięte.
|
||||
|
||||
[action]
|
||||
create_repo=tworzy repozytorium <a href="%s">%s</a>
|
||||
|
|
|
|||
|
|
@ -489,6 +489,8 @@ mirror_last_synced=Última sincronização
|
|||
watchers=Observadores
|
||||
stargazers=Usuários que estrelaram
|
||||
forks=Forks
|
||||
pick_reaction=Escolha sua reação
|
||||
reactions_more=e %d mais
|
||||
|
||||
form.reach_limit_of_creation=Você já atingiu o seu limite de %d repositórios.
|
||||
form.name_reserved=O nome de repositório '%s' é reservado e não pode ser usado.
|
||||
|
|
@ -539,6 +541,7 @@ pulls=Pull Requests
|
|||
labels=Etiquetas
|
||||
milestones=Marcos
|
||||
commits=Commits
|
||||
commit=Commit
|
||||
releases=Versões
|
||||
file_raw=Original
|
||||
file_history=Histórico
|
||||
|
|
@ -752,7 +755,6 @@ pulls.is_checking=A verificação do conflito ainda está em progresso, por favo
|
|||
pulls.can_auto_merge_desc=O merge deste pull request pode ser aplicado automaticamente.
|
||||
pulls.cannot_auto_merge_desc=O merge deste pull request não pode ser aplicado automaticamente pois há conflitos.
|
||||
pulls.cannot_auto_merge_helper=Por favor, aplique o merge manualmente para resolver os conflitos.
|
||||
pulls.merge_pull_request=Solicitação de merge de Pull Request
|
||||
pulls.open_unmerged_pull_exists=`Você não pode executar a operação de reabrir porque já existe um pull request aberto (#%d) do mesmo repositório com as mesmas informações de merge e está esperando pelo merge.`
|
||||
|
||||
milestones.new=Novo marco
|
||||
|
|
@ -804,6 +806,7 @@ wiki.new_page_button=Nova página
|
|||
wiki.delete_page_button=Excluir página
|
||||
wiki.delete_page_notice_1=Isso vai deletar a página <code>"%s"</code>. Por favor, verifique se você quer mesmo deletar esta página.
|
||||
wiki.page_already_exists=já existe uma página de wiki com o mesmo nome.
|
||||
wiki.reserved_page=O nome %s para página wiki está reservado, por favor, selecione um nome diferente.
|
||||
wiki.pages=Páginas
|
||||
wiki.last_updated=Última atualização %s
|
||||
|
||||
|
|
@ -1543,6 +1546,7 @@ no_read=Você não possui nenhuma notificação lida.
|
|||
pin=Fixar notificação
|
||||
mark_as_read=Marcar como lida
|
||||
mark_as_unread=Marcar como não lida
|
||||
mark_all_as_read=Marcar todas como lidas
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=Falha ao extrair assinatura
|
||||
|
|
|
|||
|
|
@ -489,6 +489,8 @@ mirror_last_synced=Последняя синхронизация
|
|||
watchers=Наблюдатели
|
||||
stargazers=Звездочеты
|
||||
forks=Форки
|
||||
pick_reaction=Оставьте свою оценку!
|
||||
reactions_more=и ещё %d
|
||||
|
||||
form.reach_limit_of_creation=Вы уже достигли ваш предел %d репозиториев.
|
||||
form.name_reserved=Имя репозитория '%s' зарезервировано.
|
||||
|
|
@ -529,16 +531,17 @@ bare_message=В репозитории нет файлов.
|
|||
|
||||
code=Код
|
||||
code.desc=Хранилище кода с историей изменений
|
||||
branch=Ветка
|
||||
branch=ветка
|
||||
tree=Дерево
|
||||
filter_branch_and_tag=Фильтр по ветке или тегу
|
||||
branches=Ветки
|
||||
branches=веток
|
||||
tags=Теги
|
||||
issues=Задачи
|
||||
pulls=Pull Request'ы
|
||||
labels=Метки
|
||||
milestones=Этапы
|
||||
commits=Коммиты
|
||||
commits=коммитов
|
||||
commit=коммит
|
||||
releases=Релизы
|
||||
file_raw=Исходник
|
||||
file_history=История
|
||||
|
|
@ -1544,6 +1547,7 @@ no_read=У вас нет прочитанных уведомлений.
|
|||
pin=Прикрепить уведомление
|
||||
mark_as_read=Отметить как прочитанное
|
||||
mark_as_unread=Пометить как непрочитанное
|
||||
mark_all_as_read=Пометить все как прочитанные
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=Не удалось извлечь подпись
|
||||
|
|
|
|||
|
|
@ -405,6 +405,7 @@ key_state_desc=7 天内使用过该密钥
|
|||
token_state_desc=7 天内使用过该密钥
|
||||
show_openid=在个人信息上显示
|
||||
hide_openid=在个人信息上隐藏
|
||||
ssh_disabled=SSH 被禁用
|
||||
|
||||
manage_social=管理关联社交帐户
|
||||
social_desc=这是相关联的社会帐户的列表。出于安全考虑,请确保你认识的所有这些条目,因为它们可以用于登录到您的帐户。
|
||||
|
|
@ -488,6 +489,8 @@ mirror_last_synced=上次同步时间:
|
|||
watchers=关注者
|
||||
stargazers=称赞者
|
||||
forks=派生仓库
|
||||
pick_reaction=选择你的表情
|
||||
reactions_more=再加载 %d
|
||||
|
||||
form.reach_limit_of_creation=你已经达到了您的 %d 仓库的限制。
|
||||
form.name_reserved=仓库名称 '%s' 是被保留的。
|
||||
|
|
@ -538,6 +541,7 @@ pulls=合并请求
|
|||
labels=标签
|
||||
milestones=里程碑
|
||||
commits=提交
|
||||
commit=提交
|
||||
releases=版本发布
|
||||
file_raw=原始文件
|
||||
file_history=文件历史
|
||||
|
|
@ -803,6 +807,7 @@ wiki.new_page_button=新的页面
|
|||
wiki.delete_page_button=删除页面
|
||||
wiki.delete_page_notice_1=此操作将删除页面 <code>"%s"</code>。请确保您想要删除此页。
|
||||
wiki.page_already_exists=相同名称的 Wiki 页面已经存在。
|
||||
wiki.reserved_page=wiki 页面名称 %s 是保留的, 请选择其他名称。
|
||||
wiki.pages=所有页面
|
||||
wiki.last_updated=最后更新于 %s
|
||||
|
||||
|
|
@ -813,8 +818,8 @@ activity.period.halfweekly=3 天
|
|||
activity.period.weekly=1周
|
||||
activity.period.monthly=1 个月
|
||||
activity.overview=概览
|
||||
activity.active_prs_count_1=<strong>%d</strong>活动请求
|
||||
activity.active_prs_count_n=<strong>%d</strong>活动请求
|
||||
activity.active_prs_count_1=<strong>%d</strong> 合并请求
|
||||
activity.active_prs_count_n=<strong>%d</strong> 合并请求
|
||||
activity.merged_prs_count_1=合并请求
|
||||
activity.merged_prs_count_n=合并请求
|
||||
activity.opened_prs_count_1=新合并请求
|
||||
|
|
@ -827,8 +832,8 @@ activity.title.prs_merged_by=%[2]s 由 %[1]s 合并
|
|||
activity.title.prs_opened_by=%[2]s 创建了 %[1]s
|
||||
activity.merged_prs_label=已合并
|
||||
activity.opened_prs_label=已创建
|
||||
activity.active_issues_count_1=<strong>%d</strong>活动工单
|
||||
activity.active_issues_count_n=<strong>%d</strong>活动工单
|
||||
activity.active_issues_count_1=<strong>%d</strong> 工单
|
||||
activity.active_issues_count_n=<strong>%d</strong> 工单
|
||||
activity.closed_issues_count_1=已关闭的工单
|
||||
activity.closed_issues_count_n=已关闭的工单
|
||||
activity.title.issues_1=%d 工单
|
||||
|
|
@ -977,6 +982,7 @@ settings.slack_token=令牌
|
|||
settings.slack_domain=域名
|
||||
settings.slack_channel=频道
|
||||
settings.add_discord_hook_desc=为您的仓库增加 <a href="%s">Discord</a> 集成。
|
||||
settings.add_dingtalk_hook_desc=为您的仓库增加 <a href="%s">钉钉</a> 集成。
|
||||
settings.deploy_keys=管理部署密钥
|
||||
settings.add_deploy_key=添加部署密钥
|
||||
settings.deploy_key_desc=部署密钥仅具有只读权限,它在功能上和个人用户的公开密钥有本质区别。
|
||||
|
|
@ -1050,7 +1056,7 @@ release.prerelease_helper=我们会告知用户不建议将本次发布投入生
|
|||
release.cancel=取消
|
||||
release.publish=发布版本
|
||||
release.save_draft=保存草稿
|
||||
release.edit_release=编辑发布信息
|
||||
release.edit_release=保存此次发布
|
||||
release.delete_release=删除此次发布
|
||||
release.deletion=删除版本发布操作
|
||||
release.deletion_desc=删除该版本发布将会移除相应的 Git 标签。是否继续?
|
||||
|
|
@ -1541,6 +1547,7 @@ no_read=您没有任何已读的通知。
|
|||
pin=Pin 通知
|
||||
mark_as_read=标记为已读
|
||||
mark_as_unread=标记为未读
|
||||
mark_all_as_read=全部标记为已读
|
||||
|
||||
[gpg]
|
||||
error.extract_sign=无法提取签名
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user