mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Compare commits
	
		
			66 Commits
		
	
	
		
			v1.9.2
			...
			release/v1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					3c3823dc7f | ||
| 
						 | 
					2f73fff053 | ||
| 
						 | 
					fb5af37b3e | ||
| 
						 | 
					2ef37522b6 | ||
| 
						 | 
					46ff639a13 | ||
| 
						 | 
					0b91aaf62a | ||
| 
						 | 
					4a08d574cf | ||
| 
						 | 
					f104898989 | ||
| 
						 | 
					83d04df365 | ||
| 
						 | 
					9614bb1b9f | ||
| 
						 | 
					b2c3a7d79f | ||
| 
						 | 
					76bbcf1387 | ||
| 
						 | 
					1bcbc02045 | ||
| 
						 | 
					66ceee08dc | ||
| 
						 | 
					ffff835b73 | ||
| 
						 | 
					63c54f7e1f | ||
| 
						 | 
					f9845454cf | ||
| 
						 | 
					1e1211c194 | ||
| 
						 | 
					10e549df7d | ||
| 
						 | 
					519f69eb41 | ||
| 
						 | 
					d4501ece55 | ||
| 
						 | 
					c1152b15fe | ||
| 
						 | 
					cb31f88383 | ||
| 
						 | 
					6cb9ce1367 | ||
| 
						 | 
					d93d5d7906 | ||
| 
						 | 
					5c3863c319 | ||
| 
						 | 
					80b50afe1f | ||
| 
						 | 
					20a28b785a | ||
| 
						 | 
					d330b2f52b | ||
| 
						 | 
					6ab1d5a8a0 | ||
| 
						 | 
					05f6566786 | ||
| 
						 | 
					0ea4b786cb | ||
| 
						 | 
					30718ce4ac | ||
| 
						 | 
					aeec78543b | ||
| 
						 | 
					c9b8c12bc9 | ||
| 
						 | 
					b0dcf417ea | ||
| 
						 | 
					797194d2d0 | ||
| 
						 | 
					5bac1a692a | ||
| 
						 | 
					b6fba5b459 | ||
| 
						 | 
					e90d88d5d5 | ||
| 
						 | 
					7156e2a71a | ||
| 
						 | 
					e51d91a258 | ||
| 
						 | 
					0ed5a647dd | ||
| 
						 | 
					3fc42add16 | ||
| 
						 | 
					4b9786ba62 | ||
| 
						 | 
					aaf975bff1 | ||
| 
						 | 
					267fbbf201 | ||
| 
						 | 
					9e8df4b838 | ||
| 
						 | 
					d78aa189ec | ||
| 
						 | 
					6883c007d3 | ||
| 
						 | 
					91ea086ebe | ||
| 
						 | 
					b228d22736 | ||
| 
						 | 
					c4d8d53a6d | ||
| 
						 | 
					2f71571305 | ||
| 
						 | 
					a182a80f7c | ||
| 
						 | 
					89c57487cd | ||
| 
						 | 
					bb609cacee | ||
| 
						 | 
					e7f6da386f | ||
| 
						 | 
					7727f84fe8 | ||
| 
						 | 
					5d2676089e | ||
| 
						 | 
					9bea8d825b | ||
| 
						 | 
					3cc728870a | ||
| 
						 | 
					0793b5e9c0 | ||
| 
						 | 
					bb423f9350 | ||
| 
						 | 
					4d6c8d9b13 | ||
| 
						 | 
					b6b1560701 | 
@@ -362,7 +362,7 @@ steps:
 | 
			
		||||
 | 
			
		||||
  - name: static
 | 
			
		||||
    pull: always
 | 
			
		||||
    image: techknowlogick/xgo:latest
 | 
			
		||||
    image: techknowlogick/xgo:go-1.12.x
 | 
			
		||||
    commands:
 | 
			
		||||
      - export PATH=$PATH:$GOPATH/bin
 | 
			
		||||
      - make generate
 | 
			
		||||
@@ -463,7 +463,7 @@ steps:
 | 
			
		||||
 | 
			
		||||
  - name: static
 | 
			
		||||
    pull: always
 | 
			
		||||
    image: techknowlogick/xgo:latest
 | 
			
		||||
    image: techknowlogick/xgo:go-1.12.x
 | 
			
		||||
    commands:
 | 
			
		||||
      - export PATH=$PATH:$GOPATH/bin
 | 
			
		||||
      - make generate
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										73
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -4,6 +4,79 @@ This changelog goes through all the changes that have been made in each release
 | 
			
		||||
without substantial changes to our git log; to see the highlights of what has
 | 
			
		||||
been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
			
		||||
 | 
			
		||||
## [1.9.6](https://github.com/go-gitea/gitea/releases/tag/v1.9.6) - 2019-11-13
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Allow to merge if file path contains " or \ (#8629) (#8772)
 | 
			
		||||
  * Fix 500 when edit hook (#8782) (#8790)
 | 
			
		||||
  * Fix issue with user.fullname (#8904)
 | 
			
		||||
  * Update Github Migration Test (#8897) (#8946)
 | 
			
		||||
  * Add Close() method to gogitRepository (#8901) (#8958)
 | 
			
		||||
 | 
			
		||||
## [1.9.5](https://github.com/go-gitea/gitea/releases/tag/v1.9.5) - 2019-10-30
 | 
			
		||||
* BREAKING
 | 
			
		||||
  * Hide some user information via API if user doesn't have enough permission (#8655) (#8658)
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix milestone close timestamp (#8728) (#8731)
 | 
			
		||||
  * Fix deadline on update issue or PR via API (#8699)
 | 
			
		||||
  * Fix 'New Issue Missing Milestone Comment' (#8678) (#8682)
 | 
			
		||||
  * Fix 500 when getting user as unauthenticated user (#8653) (#8662)
 | 
			
		||||
  * Use AppSubUrl for more redirections (#8647) (#8652)
 | 
			
		||||
  * Add SubURL to redirect path (#8632) (#8634) (#8640)
 | 
			
		||||
  * Fix #8582 by handling empty repos (#8587) (#8593)
 | 
			
		||||
  * Fix bug on pull requests when transfer head repository (#8571)
 | 
			
		||||
  * Add missed close in ServeBlobLFS (#8527) (#8543)
 | 
			
		||||
  * Return false if provided branch name is empty for IsBranchExist (#8485) (#8492)
 | 
			
		||||
  * Create .ssh dir as necessary (#8369) (#8486) (#8489)
 | 
			
		||||
  * Restore functionality for early gits (#7775) (#8476)
 | 
			
		||||
  * Add check for empty set when dropping indexes during migration (#8475)
 | 
			
		||||
  * Ensure Request Body Readers are closed in LFS server (#8454) (#8459)
 | 
			
		||||
  * Ensure that LFS files are relative to the LFS content path (#8455) (#8458)
 | 
			
		||||
* SECURITY
 | 
			
		||||
  * Ignore mentions for users with no access (#8395) (#8484)
 | 
			
		||||
* TESTING
 | 
			
		||||
  * Update heatmap fixtures to restore tests (#8615) (#8617)
 | 
			
		||||
 | 
			
		||||
## [1.9.4](https://github.com/go-gitea/gitea/releases/tag/v1.9.4) - 2019-10-08
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Highlight issue references (#8101) (#8404)
 | 
			
		||||
  * Fix bug when migrating a private repository #7917 (#8403)
 | 
			
		||||
  * Change general form binding to gogs form (#8334) (#8402)
 | 
			
		||||
  * Fix editor commit to new branch if PR disabled (#8375) (#8401)
 | 
			
		||||
  * Fix milestone num_issues (#8221) (#8400)
 | 
			
		||||
  * Allow users with explicit read access to give approvals (#8398)
 | 
			
		||||
  * Fix commit status in PR #8316 and PR #8321 (#8339)
 | 
			
		||||
  * Fix API for edit and delete release attachment (#8290)
 | 
			
		||||
  * Fix assets on release webhook (#8283)
 | 
			
		||||
  * Fix release API URL generation (#8239)
 | 
			
		||||
  * Allow registration when button is hidden (#8238)
 | 
			
		||||
  * MS Teams webhook misses commit messages (backport v1.9) (#8225)
 | 
			
		||||
  * Fix data race (#8206)
 | 
			
		||||
  * Fix pull merge 500 error caused by git-fetch breaking behaviors (#8194)
 | 
			
		||||
  * Fix the SSH config specification in the authorized_keys template (#8193)
 | 
			
		||||
  * Fix reading git notes from nested trees (#8189)
 | 
			
		||||
  * Fix team user api (#8172) (#8188)
 | 
			
		||||
  * Add reviewers as participants (#8124)
 | 
			
		||||
* BUILD
 | 
			
		||||
  * Use vendored go-swagger (#8087) (#8165)
 | 
			
		||||
  * Fix version-validation for GO 1.13 (go-macaron/cors) (#8389)
 | 
			
		||||
* MISC
 | 
			
		||||
  * Make show private icon when repo avatar set (#8144) (#8175)
 | 
			
		||||
 | 
			
		||||
## [1.9.3](https://github.com/go-gitea/gitea/releases/tag/v1.9.3) - 2019-09-06
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix go get from a private repository with Go 1.13 (#8100)
 | 
			
		||||
  * Strict name matching for Repository.GetTagID() (#8082)
 | 
			
		||||
  * Avoid ambiguity of branch/directory names for the git-diff-tree command (#8070)
 | 
			
		||||
  * Add change title notification for issues (#8064)
 | 
			
		||||
  * Run CORS handler first for /api routes (#7967) (#8053)
 | 
			
		||||
  * Evaluate emojis in commit messages in list view (#8044)
 | 
			
		||||
  * Fix failed to synchronize tags to releases for repository (#7990) (#7994)
 | 
			
		||||
  * Fix adding default Telegram webhook (#7972) (#7992)
 | 
			
		||||
  * Abort synchronization from LDAP source if there is some error (#7965)
 | 
			
		||||
  * Fix deformed emoji in commit message (#8071)
 | 
			
		||||
* ENHANCEMENT
 | 
			
		||||
  * Keep blame view buttons sequence consistent with normal view when viewing a file (#8007) (#8009)
 | 
			
		||||
 | 
			
		||||
## [1.9.2](https://github.com/go-gitea/gitea/releases/tag/v1.9.2) - 2019-08-22
 | 
			
		||||
* BUGFIXES
 | 
			
		||||
  * Fix wrong sender when send slack webhook (#7918) (#7924)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										12
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								Makefile
									
									
									
									
									
								
							@@ -48,6 +48,8 @@ TAGS ?=
 | 
			
		||||
 | 
			
		||||
TMPDIR := $(shell mktemp -d 2>/dev/null || mktemp -d -t 'gitea-temp')
 | 
			
		||||
 | 
			
		||||
#To update swagger use: GO111MODULE=on go get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.20.1
 | 
			
		||||
SWAGGER := GO111MODULE=on $(GO) run -mod=vendor github.com/go-swagger/go-swagger/cmd/swagger
 | 
			
		||||
SWAGGER_SPEC := templates/swagger/v1_json.tmpl
 | 
			
		||||
SWAGGER_SPEC_S_TMPL := s|"basePath": *"/api/v1"|"basePath": "{{AppSubUrl}}/api/v1"|g
 | 
			
		||||
SWAGGER_SPEC_S_JSON := s|"basePath": *"{{AppSubUrl}}/api/v1"|"basePath": "/api/v1"|g
 | 
			
		||||
@@ -101,10 +103,7 @@ generate:
 | 
			
		||||
 | 
			
		||||
.PHONY: generate-swagger
 | 
			
		||||
generate-swagger:
 | 
			
		||||
	@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
			
		||||
		GO111MODULE="on" $(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger@v0.19.0; \
 | 
			
		||||
	fi
 | 
			
		||||
	swagger generate spec -o './$(SWAGGER_SPEC)'
 | 
			
		||||
	$(SWAGGER) generate spec -o './$(SWAGGER_SPEC)'
 | 
			
		||||
	$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
 | 
			
		||||
	$(SED_INPLACE) $(SWAGGER_NEWLINE_COMMAND) './$(SWAGGER_SPEC)'
 | 
			
		||||
 | 
			
		||||
@@ -119,11 +118,8 @@ swagger-check: generate-swagger
 | 
			
		||||
 | 
			
		||||
.PHONY: swagger-validate
 | 
			
		||||
swagger-validate:
 | 
			
		||||
	@hash swagger > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
			
		||||
		$(GO) get -u github.com/go-swagger/go-swagger/cmd/swagger; \
 | 
			
		||||
	fi
 | 
			
		||||
	$(SED_INPLACE) '$(SWAGGER_SPEC_S_JSON)' './$(SWAGGER_SPEC)'
 | 
			
		||||
	swagger validate './$(SWAGGER_SPEC)'
 | 
			
		||||
	$(SWAGGER) validate './$(SWAGGER_SPEC)'
 | 
			
		||||
	$(SED_INPLACE) '$(SWAGGER_SPEC_S_TMPL)' './$(SWAGGER_SPEC)'
 | 
			
		||||
 | 
			
		||||
.PHONY: errcheck
 | 
			
		||||
 
 | 
			
		||||
@@ -374,17 +374,20 @@ func runRepoSyncReleases(c *cli.Context) error {
 | 
			
		||||
 | 
			
		||||
			if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
 | 
			
		||||
				log.Warn(" SyncReleasesWithTags: %v", err)
 | 
			
		||||
				gitRepo.Close()
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			count, err = getReleaseCount(repo.ID)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Warn(" GetReleaseCountByRepoID: %v", err)
 | 
			
		||||
				gitRepo.Close()
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			log.Trace(" repo %s releases synchronized to tags: from %d to %d",
 | 
			
		||||
				repo.FullName(), oldnum, count)
 | 
			
		||||
			gitRepo.Close()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -67,6 +67,7 @@ type Uploader interface {
 | 
			
		||||
	CreateComment(issueNumber int64, comment *Comment) error
 | 
			
		||||
	CreatePullRequest(pr *PullRequest) error
 | 
			
		||||
	Rollback() error
 | 
			
		||||
	Close()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
```
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										51
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										51
									
								
								go.mod
									
									
									
									
									
								
							@@ -3,7 +3,6 @@ module code.gitea.io/gitea
 | 
			
		||||
go 1.12
 | 
			
		||||
 | 
			
		||||
require (
 | 
			
		||||
	github.com/BurntSushi/toml v0.3.1 // indirect
 | 
			
		||||
	github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34
 | 
			
		||||
	github.com/RoaringBitmap/roaring v0.4.7 // indirect
 | 
			
		||||
	github.com/Unknwon/cae v0.0.0-20160715032808-c6aac99ea2ca
 | 
			
		||||
@@ -17,18 +16,18 @@ require (
 | 
			
		||||
	github.com/blevesearch/go-porterstemmer v0.0.0-20141230013033-23a2c8e5cf1f // indirect
 | 
			
		||||
	github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc // indirect
 | 
			
		||||
	github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 // indirect
 | 
			
		||||
	github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a // indirect
 | 
			
		||||
	github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 // indirect
 | 
			
		||||
	github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f
 | 
			
		||||
	github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c // indirect
 | 
			
		||||
	github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a // indirect
 | 
			
		||||
	github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d // indirect
 | 
			
		||||
	github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b // indirect
 | 
			
		||||
	github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe // indirect
 | 
			
		||||
	github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d // indirect
 | 
			
		||||
	github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7 // indirect
 | 
			
		||||
	github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d // indirect
 | 
			
		||||
	github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 // indirect
 | 
			
		||||
	github.com/cznic/strutil v0.0.0-20181122101858-275e90344537 // indirect
 | 
			
		||||
	github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952
 | 
			
		||||
	github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
			
		||||
	github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 // indirect
 | 
			
		||||
	github.com/edsrzf/mmap-go v1.0.0 // indirect
 | 
			
		||||
	github.com/emirpasic/gods v1.12.0
 | 
			
		||||
	github.com/etcd-io/bbolt v1.3.2 // indirect
 | 
			
		||||
	github.com/ethantkoenig/rupture v0.0.0-20180203182544-0a76f03a811a
 | 
			
		||||
@@ -40,13 +39,13 @@ require (
 | 
			
		||||
	github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
 | 
			
		||||
	github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4 // indirect
 | 
			
		||||
	github.com/facebookgo/subset v0.0.0-20150612182917-8dac2c3c4870 // indirect
 | 
			
		||||
	github.com/gliderlabs/ssh v0.1.4 // indirect
 | 
			
		||||
	github.com/gliderlabs/ssh v0.2.2 // indirect
 | 
			
		||||
	github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd // indirect
 | 
			
		||||
	github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // indirect
 | 
			
		||||
	github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443
 | 
			
		||||
	github.com/go-macaron/cache v0.0.0-20151013081102-561735312776
 | 
			
		||||
	github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df
 | 
			
		||||
	github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9
 | 
			
		||||
	github.com/go-macaron/cors v0.0.0-20190418220122-6fd6a9bfe14e
 | 
			
		||||
	github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372
 | 
			
		||||
	github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
 | 
			
		||||
	github.com/go-macaron/inject v0.0.0-20160627170012-d8a0b8677191
 | 
			
		||||
@@ -54,12 +53,13 @@ require (
 | 
			
		||||
	github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90
 | 
			
		||||
	github.com/go-redis/redis v6.15.2+incompatible
 | 
			
		||||
	github.com/go-sql-driver/mysql v1.4.1
 | 
			
		||||
	github.com/go-swagger/go-swagger v0.20.1
 | 
			
		||||
	github.com/go-xorm/core v0.6.0 // indirect
 | 
			
		||||
	github.com/go-xorm/xorm v0.7.3-0.20190620151208-f1b4f8368459
 | 
			
		||||
	github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561
 | 
			
		||||
	github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183
 | 
			
		||||
	github.com/google/go-cmp v0.3.0 // indirect
 | 
			
		||||
	github.com/google/go-github/v24 v24.0.1
 | 
			
		||||
	github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c // indirect
 | 
			
		||||
	github.com/gorilla/context v1.1.1
 | 
			
		||||
	github.com/issue9/assert v1.3.2 // indirect
 | 
			
		||||
	github.com/issue9/identicon v0.0.0-20160320065130-d36b54562f4c
 | 
			
		||||
@@ -72,7 +72,7 @@ require (
 | 
			
		||||
	github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc // indirect
 | 
			
		||||
	github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 // indirect
 | 
			
		||||
	github.com/lafriks/xormstore v1.0.0
 | 
			
		||||
	github.com/lib/pq v1.1.0
 | 
			
		||||
	github.com/lib/pq v1.2.0
 | 
			
		||||
	github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
 | 
			
		||||
	github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e
 | 
			
		||||
	github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de // indirect
 | 
			
		||||
@@ -80,16 +80,19 @@ require (
 | 
			
		||||
	github.com/markbates/goth v1.49.0
 | 
			
		||||
	github.com/mattn/go-isatty v0.0.7
 | 
			
		||||
	github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d // indirect
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.10.0
 | 
			
		||||
	github.com/mattn/go-sqlite3 v1.11.0
 | 
			
		||||
	github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75
 | 
			
		||||
	github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a
 | 
			
		||||
	github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae // indirect
 | 
			
		||||
	github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc
 | 
			
		||||
	github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5
 | 
			
		||||
	github.com/oliamb/cutter v0.2.2
 | 
			
		||||
	github.com/onsi/ginkgo v1.8.0 // indirect
 | 
			
		||||
	github.com/onsi/gomega v1.5.0 // indirect
 | 
			
		||||
	github.com/philhofer/fwd v1.0.0 // indirect
 | 
			
		||||
	github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e
 | 
			
		||||
	github.com/prometheus/client_golang v0.9.3
 | 
			
		||||
	github.com/prometheus/client_golang v1.1.0
 | 
			
		||||
	github.com/prometheus/procfs v0.0.4 // indirect
 | 
			
		||||
	github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 // indirect
 | 
			
		||||
	github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff
 | 
			
		||||
	github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca // indirect
 | 
			
		||||
@@ -99,28 +102,31 @@ require (
 | 
			
		||||
	github.com/shurcooL/sanitized_anchor_name v0.0.0-20160918041101-1dba4b3954bc // indirect
 | 
			
		||||
	github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd
 | 
			
		||||
	github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d // indirect
 | 
			
		||||
	github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff // indirect
 | 
			
		||||
	github.com/smartystreets/assertions v1.0.1 // indirect
 | 
			
		||||
	github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
 | 
			
		||||
	github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 // indirect
 | 
			
		||||
	github.com/stretchr/testify v1.3.0
 | 
			
		||||
	github.com/stretchr/testify v1.4.0
 | 
			
		||||
	github.com/syndtr/goleveldb v1.0.0 // indirect
 | 
			
		||||
	github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 // indirect
 | 
			
		||||
	github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 // indirect
 | 
			
		||||
	github.com/tstranex/u2f v1.0.0
 | 
			
		||||
	github.com/urfave/cli v1.20.0
 | 
			
		||||
	github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 // indirect
 | 
			
		||||
	github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53
 | 
			
		||||
	go.etcd.io/bbolt v1.3.2 // indirect
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443
 | 
			
		||||
	golang.org/x/net v0.0.0-20190613194153-d28f0bde5980
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759
 | 
			
		||||
	golang.org/x/sys v0.0.0-20190618155005-516e3c20635f
 | 
			
		||||
	golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
 | 
			
		||||
	golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
 | 
			
		||||
	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
 | 
			
		||||
	golang.org/x/sys v0.0.0-20190904154756-749cb33beabd
 | 
			
		||||
	golang.org/x/text v0.3.2
 | 
			
		||||
	golang.org/x/tools v0.0.0-20190618163018-fdf1049a943a // indirect
 | 
			
		||||
	golang.org/x/tools v0.0.0-20190903163617-be0da057c5e3 // indirect
 | 
			
		||||
	google.golang.org/appengine v1.6.2 // indirect
 | 
			
		||||
	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 | 
			
		||||
	gopkg.in/asn1-ber.v1 v1.0.0-20150924051756-4e86f4367175 // indirect
 | 
			
		||||
	gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e // indirect
 | 
			
		||||
	gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0
 | 
			
		||||
	gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
 | 
			
		||||
	gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0
 | 
			
		||||
	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 | 
			
		||||
	gopkg.in/ini.v1 v1.42.0
 | 
			
		||||
	gopkg.in/ini.v1 v1.46.0
 | 
			
		||||
	gopkg.in/ldap.v3 v3.0.2
 | 
			
		||||
	gopkg.in/macaron.v1 v1.3.2
 | 
			
		||||
	gopkg.in/redis.v2 v2.3.2 // indirect
 | 
			
		||||
@@ -128,7 +134,6 @@ require (
 | 
			
		||||
	gopkg.in/src-d/go-git.v4 v4.12.0
 | 
			
		||||
	gopkg.in/stretchr/testify.v1 v1.2.2 // indirect
 | 
			
		||||
	gopkg.in/testfixtures.v2 v2.5.0
 | 
			
		||||
	gopkg.in/yaml.v2 v2.2.2 // indirect
 | 
			
		||||
	mvdan.cc/xurls/v2 v2.0.0
 | 
			
		||||
	strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a
 | 
			
		||||
	xorm.io/builder v0.3.5
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										379
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										379
									
								
								go.sum
									
									
									
									
									
								
							@@ -1,11 +1,23 @@
 | 
			
		||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
			
		||||
cloud.google.com/go v0.30.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
			
		||||
cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
 | 
			
		||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 | 
			
		||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
 | 
			
		||||
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
 | 
			
		||||
cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
 | 
			
		||||
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
 | 
			
		||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
 | 
			
		||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
 | 
			
		||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
 | 
			
		||||
github.com/OneOfOne/xxhash v1.2.5/go.mod h1:eZbhyaAYD41SGSSsnmcpxVoRiQ/MPUTjUdIIOT9Um7Q=
 | 
			
		||||
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34 h1:UsHpWO0Elp6NaWVARdZHjiYwkhrspHVEGsyIKPb9OI8=
 | 
			
		||||
github.com/PuerkitoBio/goquery v0.0.0-20170324135448-ed7d758e9a34/go.mod h1:T9ezsOHcCrDCgA8aF1Cqr3sSYbO/xgdy8/R/XiIMAhA=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
 | 
			
		||||
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
 | 
			
		||||
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
 | 
			
		||||
github.com/RoaringBitmap/roaring v0.4.7 h1:eGUudvFzvF7Kxh7JjYvXfI1f7l22/2duFby7r5+d4oc=
 | 
			
		||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
 | 
			
		||||
github.com/Unknwon/cae v0.0.0-20160715032808-c6aac99ea2ca h1:xU8R31tsvj6TesCBog973+UgI3TXjh/LqN5clki6hcc=
 | 
			
		||||
@@ -24,12 +36,18 @@ github.com/andybalholm/cascadia v0.0.0-20161224141413-349dd0209470 h1:4jHLmof+Hb
 | 
			
		||||
github.com/andybalholm/cascadia v0.0.0-20161224141413-349dd0209470/go.mod h1:3I+3V7B6gTBYfdpYgIG2ymALS9H+5VDKUl3lHH7ToM4=
 | 
			
		||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
 | 
			
		||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
 | 
			
		||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
 | 
			
		||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
 | 
			
		||||
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
 | 
			
		||||
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 | 
			
		||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
 | 
			
		||||
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
 | 
			
		||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
 | 
			
		||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
 | 
			
		||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
 | 
			
		||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
 | 
			
		||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
 | 
			
		||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
 | 
			
		||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
 | 
			
		||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
 | 
			
		||||
github.com/blevesearch/bleve v0.0.0-20190214220507-05d86ea8f6e3 h1:vinCy/rcjbtxWnMiw11CbMKcuyNi+y4L4MbZUpk7m4M=
 | 
			
		||||
@@ -42,21 +60,35 @@ github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc h1:7OfDAkuAGx7
 | 
			
		||||
github.com/blevesearch/segment v0.0.0-20160105220820-db70c57796cc/go.mod h1:IInt5XRvpiGE09KOk9mmCMLjHhydIhNPKPPFLFBB7L8=
 | 
			
		||||
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26 h1:NGpwhs9FOwddM6TptNrq2ycby4s24TcppSe5uG4DA/Q=
 | 
			
		||||
github.com/boombuler/barcode v0.0.0-20161226211916-fe0f26ff6d26/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a h1:k5TuEkqEYCRs8+66WdOkswWOj+L/YbP5ruainvn94wg=
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20160117192205-fb1f79c6b65a/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668 h1:U/lr3Dgy4WK+hNk4tyD+nuGjpVLPEHuJSFXMw11/HPA=
 | 
			
		||||
github.com/bradfitz/gomemcache v0.0.0-20190329173943-551aad21a668/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
 | 
			
		||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
 | 
			
		||||
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f h1:REH9VH5ubNR0skLaOxK7TRJeRbE2dDfvaouQo8FsRcA=
 | 
			
		||||
github.com/chaseadamsio/goorgeous v0.0.0-20170901132237-098da33fde5f/go.mod h1:6QaC0vFoKWYDth94dHFNgRT2YkT5FHdQp/Yx15aAAi0=
 | 
			
		||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
 | 
			
		||||
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
 | 
			
		||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
 | 
			
		||||
github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c h1:K4FIibkr4//ziZKOKmt4RL0YImuTjLLBtwElf+F2lSQ=
 | 
			
		||||
github.com/couchbase/gomemcached v0.0.0-20181122193126-5125a94a666c/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a h1:Y5XsLCEhtEI8qbD9RP3Qlv5FXdTDHxZM9UPUnMRgBp8=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
 | 
			
		||||
github.com/corbym/gocrest v1.0.3 h1:gwEdq6RkTmq+09CTuM29DfKOCtZ7G7bcyxs3IZ6EVdU=
 | 
			
		||||
github.com/corbym/gocrest v1.0.3/go.mod h1:maVFL5lbdS2PgfOQgGRWDYTeunSWQeiEgoNdTABShCs=
 | 
			
		||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 | 
			
		||||
github.com/coreos/bbolt v1.3.3/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
 | 
			
		||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 | 
			
		||||
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
 | 
			
		||||
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
 | 
			
		||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 | 
			
		||||
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
 | 
			
		||||
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
			
		||||
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
 | 
			
		||||
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
 | 
			
		||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d h1:XMf4E1U+b9E3ElF0mjvfXZdflBRZz4gLp16nQ/QSHQM=
 | 
			
		||||
github.com/couchbase/gomemcached v0.0.0-20190515232915-c4b4ca0eb21d/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b h1:bZ9rKU2/V8sY+NulSfxDOnXTWcs1rySqdF1sVepihvo=
 | 
			
		||||
github.com/couchbase/goutils v0.0.0-20190315194238-f9d42b11473b/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs=
 | 
			
		||||
github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe h1:2o6Y7KMjJNsuMTF8f2H2eTKRhqH7+bQbjr+D+LnhE5M=
 | 
			
		||||
github.com/couchbase/vellum v0.0.0-20190111184608-e91b68ff3efe/go.mod h1:prYTC8EgTu3gwbqJihkud9zRXISvyulAplQ6exdCo1g=
 | 
			
		||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d h1:lsBRLJe/ET6DjCaRblGwls80dOcOzhFVNJrO6uaMrMQ=
 | 
			
		||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190117181324-d904413d884d/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
 | 
			
		||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7 h1:1XjEY/gnjQ+AfXef2U6dxCquhiRzkEpxZuWqs+QxTL8=
 | 
			
		||||
github.com/couchbaselabs/go-couchbase v0.0.0-20190708161019-23e7ca2ce2b7/go.mod h1:mby/05p8HE5yHEAKiIH/555NoblMs7PtW6NrYshDruc=
 | 
			
		||||
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
 | 
			
		||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d h1:SwD98825d6bdB+pEuTxWOXiSjBrHdOl/UVp75eI7JT8=
 | 
			
		||||
github.com/cznic/b v0.0.0-20181122101859-a26611c4d92d/go.mod h1:URriBxXwVq5ijiJ12C7iIZqlA69nTlI+LgI6/pwftG8=
 | 
			
		||||
github.com/cznic/mathutil v0.0.0-20181122101859-297441e03548 h1:iwZdTE0PVqJCos1vaoKsclOGD3ADKpshg3SRtYBbwso=
 | 
			
		||||
@@ -71,8 +103,11 @@ github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44/go.mod h1:xN
 | 
			
		||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 | 
			
		||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
 | 
			
		||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
			
		||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712 h1:aaQcKT9WumO6JEJcRyTqFVq4XUZiUcKR2/GI31TOcz8=
 | 
			
		||||
github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 | 
			
		||||
github.com/dgryski/go-sip13 v0.0.0-20190329191031-25c5027a8c7b/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
			
		||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
			
		||||
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
			
		||||
github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
 | 
			
		||||
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
 | 
			
		||||
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
 | 
			
		||||
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
 | 
			
		||||
github.com/etcd-io/bbolt v1.3.2 h1:RLRQ0TKLX7DlBRXAJHvbmXL17Q3KNnTBtZ9B6Qo+/Y0=
 | 
			
		||||
@@ -99,14 +134,18 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
 | 
			
		||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
 | 
			
		||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
 | 
			
		||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
 | 
			
		||||
github.com/gliderlabs/ssh v0.1.3/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 | 
			
		||||
github.com/gliderlabs/ssh v0.1.4 h1:5N8AYXpaQAPy0L7linKa5aI+WRfyYagAhjksVzxh+mI=
 | 
			
		||||
github.com/gliderlabs/ssh v0.1.4/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 | 
			
		||||
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
 | 
			
		||||
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
 | 
			
		||||
github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 | 
			
		||||
github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q=
 | 
			
		||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd h1:r04MMPyLHj/QwZuMJ5+7tJcBr1AQjpiAK/rZWRrQT7o=
 | 
			
		||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
 | 
			
		||||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e h1:SiEs4J3BKVIeaWrH3tKaz3QLZhJ68iJ/A4xrzIoE5+Y=
 | 
			
		||||
github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
 | 
			
		||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 | 
			
		||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 | 
			
		||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 | 
			
		||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
 | 
			
		||||
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 h1:i801KPR7j76uRMLLlGVyb0hiYbgX1FM5+ur81TJWzIw=
 | 
			
		||||
@@ -115,8 +154,8 @@ github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5
 | 
			
		||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok=
 | 
			
		||||
github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78=
 | 
			
		||||
github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA=
 | 
			
		||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9 h1:A0QGzY6UHHEil0I2e7C21JenNNG0mmrj5d9SFWTlgr8=
 | 
			
		||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
 | 
			
		||||
github.com/go-macaron/cors v0.0.0-20190418220122-6fd6a9bfe14e h1:auESkcVctNZnNl4EH0TuoCSJMJ7Q7ShU8FS6lDEsAC4=
 | 
			
		||||
github.com/go-macaron/cors v0.0.0-20190418220122-6fd6a9bfe14e/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
 | 
			
		||||
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=
 | 
			
		||||
github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372/go.mod h1:oZGMxI7MBnicI0jJqJvH4qQzyrWKhtiKxLSJKHC+ydc=
 | 
			
		||||
github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f h1:wDKrZFc9pYJlqFOf7EzGbFMrSFFtyHt3plr2uTdo8Rg=
 | 
			
		||||
@@ -127,12 +166,62 @@ github.com/go-macaron/session v0.0.0-20190131233854-0a0a789bf193 h1:z/nqwd+ql/r6
 | 
			
		||||
github.com/go-macaron/session v0.0.0-20190131233854-0a0a789bf193/go.mod h1:ScEJm9Gk+ez5JJTml5WlBIqavAfuE5nF8e4Gvyz/X+A=
 | 
			
		||||
github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90 h1:3wYKrRg9IjUMfaf3H0Hh7M5Li9ge79Y7aw2yujHa2jQ=
 | 
			
		||||
github.com/go-macaron/toolbox v0.0.0-20180818072302-a77f45a7ce90/go.mod h1:Ut/NmkIMGVYlEdJBzEZgWVWG5ZpYS9BLmUgXfAgi+qM=
 | 
			
		||||
github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI=
 | 
			
		||||
github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
 | 
			
		||||
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
 | 
			
		||||
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
 | 
			
		||||
github.com/go-openapi/analysis v0.19.4 h1:1TjOzrWkj+9BrjnM1yPAICbaoC0FyfD49oVkTBrSSa0=
 | 
			
		||||
github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
 | 
			
		||||
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
 | 
			
		||||
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
 | 
			
		||||
github.com/go-openapi/errors v0.19.2 h1:a2kIyV3w+OS3S97zxUndRVD46+FhGOUBDFY7nmu4CsY=
 | 
			
		||||
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
 | 
			
		||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
 | 
			
		||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.2 h1:A9+F4Dc/MCNB5jibxf6rRvOvR/iFgQdyNx9eIhnGqq0=
 | 
			
		||||
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
 | 
			
		||||
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
 | 
			
		||||
github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 | 
			
		||||
github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 | 
			
		||||
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
 | 
			
		||||
github.com/go-openapi/loads v0.19.2 h1:rf5ArTHmIJxyV5Oiks+Su0mUens1+AjpkPoWr5xFRcI=
 | 
			
		||||
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
 | 
			
		||||
github.com/go-openapi/runtime v0.0.0-20180920151709-4f900dc2ade9/go.mod h1:6v9a6LTXWQCdL8k1AO3cvqx5OtZY/Y9wKTgaoP6YRfA=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.0/go.mod h1:OwNfisksmmaZse4+gpV3Ne9AyMOlP1lt4sK4FXt0O64=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.4 h1:csnOgcgAiuGoM/Po7PEpKDoNulCcF3FGbSnbHfxgjMI=
 | 
			
		||||
github.com/go-openapi/runtime v0.19.4/go.mod h1:X277bwSUBxVlCYR3r7xgZZGKVvBd/29gLDlFGtJ8NL4=
 | 
			
		||||
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
 | 
			
		||||
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
 | 
			
		||||
github.com/go-openapi/spec v0.19.2 h1:SStNd1jRcYtfKCN7R0laGNs80WYYvn5CbBjM2sOmCrE=
 | 
			
		||||
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
 | 
			
		||||
github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
 | 
			
		||||
github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU=
 | 
			
		||||
github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY=
 | 
			
		||||
github.com/go-openapi/strfmt v0.19.2 h1:clPGfBnJohokno0e+d7hs6Yocrzjlgz6EsQSDncCRnE=
 | 
			
		||||
github.com/go-openapi/strfmt v0.19.2/go.mod h1:0yX7dbo8mKIvc3XSKp7MNfxw4JytCfCD6+bY1AVL9LU=
 | 
			
		||||
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 | 
			
		||||
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
 | 
			
		||||
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 | 
			
		||||
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
 | 
			
		||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
 | 
			
		||||
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
 | 
			
		||||
github.com/go-openapi/validate v0.19.2 h1:ky5l57HjyVRrsJfd2+Ro5Z9PjGuKbsmftwyMtk8H7js=
 | 
			
		||||
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
 | 
			
		||||
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
 | 
			
		||||
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
 | 
			
		||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
 | 
			
		||||
github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
 | 
			
		||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
 | 
			
		||||
github.com/go-swagger/go-swagger v0.20.1 h1:37XFujv7lYHLOKawfzLDg4STwwgB5zhPjodN33asJto=
 | 
			
		||||
github.com/go-swagger/go-swagger v0.20.1/go.mod h1:LoTpv6FHYXUvYnECHNLvi/qYNybk0d9wkJGH1cTANWE=
 | 
			
		||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013 h1:l9rI6sNaZgNC0LnF3MiE+qTmyBA/tZAg1rtyrGbUMK0=
 | 
			
		||||
github.com/go-swagger/scan-repo-boundary v0.0.0-20180623220736-973b3573c013/go.mod h1:b65mBPzqzZWxOZGxSWrqs4GInLIn+u99Q9q7p+GKni0=
 | 
			
		||||
github.com/go-xorm/core v0.6.0 h1:tp6hX+ku4OD9khFZS8VGBDRY3kfVCtelPfmkgCyHxL0=
 | 
			
		||||
github.com/go-xorm/core v0.6.0/go.mod h1:d8FJ9Br8OGyQl12MCclmYBuBqqxsyeedpXciV5Myih8=
 | 
			
		||||
github.com/go-xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:9wScpmSP5A3Bk8V3XHWUcJmYTh+ZnlHVyc+A4oZYS3Y=
 | 
			
		||||
@@ -144,28 +233,58 @@ github.com/gogits/chardet v0.0.0-20150115103509-2404f7772561/go.mod h1:YgYOrVn3N
 | 
			
		||||
github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183 h1:EBTlva3AOSb80G3JSwY6ZMdILEZJ1JKuewrbqrNjWuE=
 | 
			
		||||
github.com/gogits/cron v0.0.0-20160810035002-7f3990acf183/go.mod h1:pX+V62FFmklia2fhP3P4YSY6iJdPO5jIDKFQ5fEd5QE=
 | 
			
		||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 | 
			
		||||
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 | 
			
		||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
 | 
			
		||||
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 | 
			
		||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
 | 
			
		||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 | 
			
		||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
 | 
			
		||||
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
 | 
			
		||||
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
 | 
			
		||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
 | 
			
		||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
 | 
			
		||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w=
 | 
			
		||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
 | 
			
		||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
			
		||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
 | 
			
		||||
github.com/google/go-cmp v0.2.0 h1:+dTQ8DZQJz0Mb/HjFlkptS1FeQ4cWSnN941F8aEG4SQ=
 | 
			
		||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
 | 
			
		||||
github.com/google/go-cmp v0.3.0 h1:crn/baboCvb5fXaQ0IJ1SGTsTVrWpDsCWC8EGETZijY=
 | 
			
		||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg=
 | 
			
		||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
			
		||||
github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY=
 | 
			
		||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
 | 
			
		||||
github.com/google/go-github/v24 v24.0.1 h1:KCt1LjMJEey1qvPXxa9SjaWxwTsCWSq6p2Ju57UR4Q4=
 | 
			
		||||
github.com/google/go-github/v24 v24.0.1/go.mod h1:CRqaW1Uns1TCkP0wqTpxYyRxRjxwvKU/XSS44u6X74M=
 | 
			
		||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
 | 
			
		||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
 | 
			
		||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
			
		||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
 | 
			
		||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 | 
			
		||||
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 | 
			
		||||
github.com/google/pprof v0.0.0-20190723021845-34ac40c74b70/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
 | 
			
		||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
 | 
			
		||||
github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
 | 
			
		||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
			
		||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
 | 
			
		||||
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e h1:JKmoR8x90Iww1ks85zJ1lfDGgIiMDuIptTOhJq+zKyg=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c h1:7lF+Vz0LqiRidnzC1Oq86fpX1q/iEv2KJdrCtttYjT4=
 | 
			
		||||
github.com/gopherjs/gopherjs v0.0.0-20190430165422-3e4dfb77656c/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
 | 
			
		||||
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
 | 
			
		||||
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
 | 
			
		||||
github.com/gorilla/handlers v1.4.2 h1:0QniY0USkHQ1RGCLfKxeNHK9bkDHGRYGNDFBCS+YARg=
 | 
			
		||||
github.com/gorilla/handlers v1.4.2/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
 | 
			
		||||
github.com/gorilla/mux v1.6.2 h1:Pgr17XVTNXAk3q/r4CpKzC5xBM/qW1uVLV+IhRZpIIk=
 | 
			
		||||
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
 | 
			
		||||
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1 h1:LqbZZ9sNMWVjeXS4NN5oVvhMjDyLhmA1LG86oSo+IqY=
 | 
			
		||||
@@ -174,6 +293,16 @@ github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyC
 | 
			
		||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
 | 
			
		||||
github.com/gorilla/sessions v1.1.1 h1:YMDmfaK68mUixINzY/XjscuJ47uXFWSSHzFbBQM0PrE=
 | 
			
		||||
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
 | 
			
		||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
 | 
			
		||||
github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
 | 
			
		||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
 | 
			
		||||
github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 | 
			
		||||
github.com/grpc-ecosystem/grpc-gateway v1.9.6/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
 | 
			
		||||
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 | 
			
		||||
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
 | 
			
		||||
github.com/hashicorp/golang-lru v0.5.3/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
 | 
			
		||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 | 
			
		||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 | 
			
		||||
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
 | 
			
		||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
 | 
			
		||||
github.com/issue9/assert v1.3.2 h1:IaTa37u4m1fUuTH9K9ldO5IONKVDXjLiUO1T9vj0OF0=
 | 
			
		||||
@@ -195,6 +324,10 @@ github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U
 | 
			
		||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
 | 
			
		||||
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
 | 
			
		||||
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
 | 
			
		||||
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
 | 
			
		||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
 | 
			
		||||
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
 | 
			
		||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
 | 
			
		||||
github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 | 
			
		||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
 | 
			
		||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
 | 
			
		||||
@@ -205,6 +338,9 @@ github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e h1:RgQk53JHp
 | 
			
		||||
github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
 | 
			
		||||
github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6 h1:9mszGwKDxHEY2cy+9XxCQKWIfkGPSAEFrcN8ghzyAKg=
 | 
			
		||||
github.com/keybase/go-crypto v0.0.0-20170605145657-00ac4db533f6/go.mod h1:ghbZscTyKdM07+Fw3KSi0hcJm+AlEUWj8QLlPtijN/M=
 | 
			
		||||
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
 | 
			
		||||
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
 | 
			
		||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 | 
			
		||||
github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f h1:tCnZKEmDovgV4jmsclh6CuKk9AMzTzyVWfejgkgccVg=
 | 
			
		||||
github.com/klauspost/compress v0.0.0-20161025140425-8df558b6cb6f/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
 | 
			
		||||
github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc h1:WW8B7p7QBnFlqRVv/k6ro/S8Z7tCnYjJHcQNScx9YVs=
 | 
			
		||||
@@ -212,18 +348,21 @@ github.com/klauspost/cpuid v0.0.0-20160302075316-09cded8978dc/go.mod h1:Pj4uuM52
 | 
			
		||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6 h1:KAZ1BW2TCmT6PRihDPpocIy1QTtsAsrx6TneU/4+CMg=
 | 
			
		||||
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
 | 
			
		||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 | 
			
		||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 | 
			
		||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
 | 
			
		||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
 | 
			
		||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
			
		||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
			
		||||
github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA=
 | 
			
		||||
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
 | 
			
		||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
 | 
			
		||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
			
		||||
github.com/lafriks/xormstore v1.0.0 h1:P/IJzNSIpjXl/Up3o2Td5ZU/x4v6DEKLMaPQJGtmJCk=
 | 
			
		||||
github.com/lafriks/xormstore v1.0.0/go.mod h1:dD8vHNRfEp3Uy+JvX9cMi2SXcRKJ0x4pYKsZuy843Ic=
 | 
			
		||||
github.com/lib/pq v1.0.0 h1:X5PMW56eZitiTeO7tKzZxFCSpbFZJtkMMooicw2us9A=
 | 
			
		||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.1.0 h1:/5u4a+KGJptBRqGzPvYQL9p0d/tPR4S31+Tnzj9lEO4=
 | 
			
		||||
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
 | 
			
		||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
			
		||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96 h1:uNwtsDp7ci48vBTTxDuwcoTXz4lwtDTe7TjCQ0noaWY=
 | 
			
		||||
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96/go.mod h1:mmIfjCSQlGYXmJ95jFN84AkQFnVABtKuJL8IrzwvUKQ=
 | 
			
		||||
github.com/lunny/levelqueue v0.0.0-20190217115915-02b525a4418e h1:GSprKUrG9wNgwQgROvjPGXmcZrg4OLslOuZGB0uJjx8=
 | 
			
		||||
@@ -232,6 +371,14 @@ github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de h1:nyxwRdWHAVxpFcDThedEg
 | 
			
		||||
github.com/lunny/log v0.0.0-20160921050905-7887c61bf0de/go.mod h1:3q8WtuPQsoRbatJuy3nvq/hRSvuBJrHHr+ybPPiNvHQ=
 | 
			
		||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af h1:UaWHNBdukWrSG3DRvHFR/hyfg681fceqQDYVTBncKfQ=
 | 
			
		||||
github.com/lunny/nodb v0.0.0-20160621015157-fc1ef06ad4af/go.mod h1:Cqz6pqow14VObJ7peltM+2n3PWOz7yTrfUuGbVFkzN0=
 | 
			
		||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
			
		||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
 | 
			
		||||
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
 | 
			
		||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
 | 
			
		||||
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
 | 
			
		||||
github.com/markbates/goth v1.49.0 h1:qQ4Ti4WaqAxNAggOC+4s5M85sMVfMJwQn/Xkp73wfgI=
 | 
			
		||||
github.com/markbates/goth v1.49.0/go.mod h1:zZmAw0Es0Dpm7TT/4AdN14QrkiWLMrrU9Xei1o+/mdA=
 | 
			
		||||
@@ -241,6 +388,8 @@ github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d h1:m+dSK37rFf2fqppZh
 | 
			
		||||
github.com/mattn/go-oci8 v0.0.0-20190320171441-14ba190cf52d/go.mod h1:/M9VLO+lUPmxvoOK2PfWRZ8mTtB4q1Hy9lEGijv9Nr8=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.11.0 h1:LDdKkqtYlom37fkvqs8rMPFKAMe8+SgjbwZ6ex1/A/Q=
 | 
			
		||||
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
 | 
			
		||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
 | 
			
		||||
github.com/mcuadros/go-version v0.0.0-20190308113854-92cdf37c5b75 h1:Pijfgr7ZuvX7QIQiEwLdRVr3RoMG+i0SbBO1Qu+7yVk=
 | 
			
		||||
@@ -249,6 +398,12 @@ github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a h1:d18LCO3
 | 
			
		||||
github.com/microcosm-cc/bluemonday v0.0.0-20161012083705-f77f16ffc87a/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
 | 
			
		||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
 | 
			
		||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
 | 
			
		||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
 | 
			
		||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
			
		||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
			
		||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
 | 
			
		||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c h1:3wkDRdxK92dF+c1ke2dtj7ZzemFWBHB9plnJOtlwdFA=
 | 
			
		||||
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
 | 
			
		||||
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae h1:VeRdUYdCw49yizlSbMEn2SZ+gT+3IUKx8BqxyQdz+BY=
 | 
			
		||||
@@ -256,6 +411,7 @@ github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE
 | 
			
		||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc h1:z1PgdCCmYYVL0BoJTUgmAq1p7ca8fzYIPsNyfsN3xAU=
 | 
			
		||||
github.com/msteinert/pam v0.0.0-20151204160544-02ccfbfaf0cc/go.mod h1:np1wUFZ6tyoke22qDJZY40URn9Ae51gX7ljIWXN5TJs=
 | 
			
		||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
			
		||||
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
 | 
			
		||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5 h1:BvoENQQU+fZ9uukda/RzCAL/191HHwJA5b13R6diVlY=
 | 
			
		||||
github.com/nfnt/resize v0.0.0-20160724205520-891127d8d1b5/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
 | 
			
		||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 | 
			
		||||
@@ -264,10 +420,18 @@ github.com/oliamb/cutter v0.2.2/go.mod h1:4BenG2/4GuRBDbVm/OPahDVqbrOemzpPiG5mi1
 | 
			
		||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
 | 
			
		||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/ginkgo v1.8.0 h1:VkHVNpR4iVnU8XQR6DBm8BqYjN7CRzw+xKUbVVbbW9w=
 | 
			
		||||
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
 | 
			
		||||
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
 | 
			
		||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/onsi/gomega v1.5.0 h1:izbySO9zDPmjJ8rDjLvkA2zJHIo+HkYXHnf7eN7SSyo=
 | 
			
		||||
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
 | 
			
		||||
github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
 | 
			
		||||
github.com/pelletier/go-buffruneio v0.2.0 h1:U4t4R6YkofJ5xHm3dJzuRpPZ0mr5MMCoAWooScCR7aA=
 | 
			
		||||
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
 | 
			
		||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
 | 
			
		||||
github.com/pelletier/go-toml v1.4.0 h1:u3Z1r+oOXJIkxqw34zVhyPgjBsm6X2wn21NWs/HfSeg=
 | 
			
		||||
github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo=
 | 
			
		||||
github.com/philhofer/fwd v1.0.0 h1:UbZqGr5Y38ApvM/V/jEljVxwocdweyH+vmYvRPBnbqQ=
 | 
			
		||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
 | 
			
		||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
			
		||||
@@ -275,25 +439,42 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
 | 
			
		||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 | 
			
		||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 | 
			
		||||
github.com/pquerna/cachecontrol v0.0.0-20180517163645-1555304b9b35/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
 | 
			
		||||
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e h1:ApqncJ84HYN8x8x5WV1T1YWDuPRF/0aXZhr91LnRMCQ=
 | 
			
		||||
github.com/pquerna/otp v0.0.0-20160912161815-54653902c20e/go.mod h1:Zad1CMQfSQZI5KLpahDiSUX4tMMREnXw98IvL1nhgMk=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
 | 
			
		||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
 | 
			
		||||
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
 | 
			
		||||
github.com/prometheus/client_golang v1.1.0 h1:BQ53HtBmfOitExawJ6LokA4x8ov/z0SYYb0+HxJfRI8=
 | 
			
		||||
github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4 h1:gQz4mCbXsO+nc9n1hCxHcGA3Zx3Eo+UHZoInFGUIXNM=
 | 
			
		||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
 | 
			
		||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
 | 
			
		||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
 | 
			
		||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 | 
			
		||||
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
 | 
			
		||||
github.com/prometheus/common v0.6.0 h1:kRhiuYSXR3+uv2IbVbZhUxK5zVD/2pp3Gd2PpvPkpEo=
 | 
			
		||||
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
 | 
			
		||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 | 
			
		||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
 | 
			
		||||
github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 | 
			
		||||
github.com/prometheus/procfs v0.0.4 h1:w8DjqFMJDjuVwdZBQoOozr4MVWOnwF7RcL/7uxBjY78=
 | 
			
		||||
github.com/prometheus/procfs v0.0.4/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
 | 
			
		||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
 | 
			
		||||
github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
 | 
			
		||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001 h1:YDeskXpkNDhPdWN3REluVa46HQOVuVkjkd2sWnrABNQ=
 | 
			
		||||
github.com/remyoudompheng/bigfft v0.0.0-20190321074620-2f0d2b0e0001/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
 | 
			
		||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
 | 
			
		||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
 | 
			
		||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
 | 
			
		||||
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff h1:g9ZlAHmkc/h5So+OjNCkZWh+FjuKEOOOoyRkqlGA8+c=
 | 
			
		||||
github.com/russross/blackfriday v0.0.0-20180428102519-11635eb403ff/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
 | 
			
		||||
github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca h1:NugYot0LIVPxTvN8n+Kvkn6TrbMyxQiuvKdEwFdR9vI=
 | 
			
		||||
@@ -313,14 +494,31 @@ github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJV
 | 
			
		||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d h1:qQWKKOvHN7Q9c6GdmUteCef2F9ubxMpxY1IKwpIKz68=
 | 
			
		||||
github.com/siddontang/go-snappy v0.0.0-20140704025258-d8f7bb82a96d/go.mod h1:vq0tzqLRu6TS7Id0wMo2N5QzJoKedVeovOpHjnykSzY=
 | 
			
		||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
 | 
			
		||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304 h1:Jpy1PXuP99tXNrhbq2BaPz9B+jNAvH1JPQQpG/9GCXY=
 | 
			
		||||
github.com/smartystreets/assertions v0.0.0-20190116191733-b6c0e53d7304/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
 | 
			
		||||
github.com/smartystreets/assertions v1.0.1 h1:voD4ITNjPL5jjBfgR/r8fPIIBrliWrWHeiJApdr3r4w=
 | 
			
		||||
github.com/smartystreets/assertions v1.0.1/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff h1:86HlEv0yBCry9syNuylzqznKXDK11p6D0DT596yNMys=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190306220146-200a235640ff/go.mod h1:KSQcGKpxUMHk3nbYzs/tIBAM2iDooCn0BmttHOJEbLs=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 h1:WN9BUFbdyOsSH/XohnWpXOlq9NBD5sGAB2FciQMUEe8=
 | 
			
		||||
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
 | 
			
		||||
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
 | 
			
		||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 | 
			
		||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
 | 
			
		||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
 | 
			
		||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
 | 
			
		||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
 | 
			
		||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
 | 
			
		||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
 | 
			
		||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
 | 
			
		||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
 | 
			
		||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 | 
			
		||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
 | 
			
		||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
 | 
			
		||||
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
 | 
			
		||||
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
 | 
			
		||||
github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2 h1:JNEGSiWg6D3lcBCMCBqN3ELniXujt+0QNHLhNnO0w3s=
 | 
			
		||||
@@ -328,60 +526,121 @@ github.com/steveyen/gtreap v0.0.0-20150807155958-0abe01ef9be2/go.mod h1:mjqs7N0Q
 | 
			
		||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
 | 
			
		||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
			
		||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 | 
			
		||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
 | 
			
		||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
			
		||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 | 
			
		||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
			
		||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
 | 
			
		||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 | 
			
		||||
github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66 h1:AwmkkZT+TucFotNCL+aNJ/0KCMsRtlXN9fs8uoOMSRk=
 | 
			
		||||
github.com/syndtr/goleveldb v0.0.0-20190203031304-2f17a3356c66/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
 | 
			
		||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
 | 
			
		||||
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481 h1:HOxvxvnntLiPn123Fk+twfUhCQdMDaqmb0cclArW0T0=
 | 
			
		||||
github.com/tecbot/gorocksdb v0.0.0-20181010114359-8752a9433481/go.mod h1:ahpPrc7HpcfEWDQRZEmnXMzHY03mLDYMCxeDzy46i+8=
 | 
			
		||||
github.com/tidwall/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
 | 
			
		||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 | 
			
		||||
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200 h1:ZVvr38DYEyOPyelySqvF0I9I++85NnUMsWkroBDS4fs=
 | 
			
		||||
github.com/tinylib/msgp v0.0.0-20180516164116-c8cf64dff200/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
 | 
			
		||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
 | 
			
		||||
github.com/toqueteos/webbrowser v1.2.0 h1:tVP/gpK69Fx+qMJKsLE7TD8LuGWPnEV71wBN9rrstGQ=
 | 
			
		||||
github.com/toqueteos/webbrowser v1.2.0/go.mod h1:XWoZq4cyp9WeUeak7w7LXRUQf1F1ATJMir8RTqb4ayM=
 | 
			
		||||
github.com/tstranex/u2f v1.0.0 h1:HhJkSzDDlVSVIVt7pDJwCHQj67k7A5EeBgPmeD+pVsQ=
 | 
			
		||||
github.com/tstranex/u2f v1.0.0/go.mod h1:eahSLaqAS0zsIEv80+vXT7WanXs7MQQDg3j3wGBSayo=
 | 
			
		||||
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 | 
			
		||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
 | 
			
		||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
 | 
			
		||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
 | 
			
		||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
 | 
			
		||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621 h1:E8u341JM/N8LCnPXBV6ZFD1RKo/j+qHl1XOqSV+GstA=
 | 
			
		||||
github.com/willf/bitset v0.0.0-20180426185212-8ce1146b8621/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
 | 
			
		||||
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
 | 
			
		||||
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
 | 
			
		||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 | 
			
		||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 | 
			
		||||
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53 h1:HsIQ6yAjfjQ3IxPGrTusxp6Qxn92gNVq2x5CbvQvx3w=
 | 
			
		||||
github.com/yohcop/openid-go v0.0.0-20160914080427-2c050d2dae53/go.mod h1:f6elajwZV+xceiaqgRL090YzLEDGSbqr3poGL3ZgXYo=
 | 
			
		||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
 | 
			
		||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
 | 
			
		||||
go.etcd.io/bbolt v1.3.2 h1:Z/90sZLPOeCy2PwprqkFa25PdkusRzaj9P8zm/KNyvk=
 | 
			
		||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
			
		||||
go.etcd.io/bbolt v1.3.3 h1:MUGmc65QhB3pIlaQ5bB4LwqSj6GIonVJXpZiaKNyaKk=
 | 
			
		||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.1.0 h1:aeOqSrhl9eDRAap/3T5pCfMBEBxZ0vuXBP+RMtp2KX8=
 | 
			
		||||
go.mongodb.org/mongo-driver v1.1.0/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
 | 
			
		||||
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
 | 
			
		||||
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
 | 
			
		||||
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 | 
			
		||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
 | 
			
		||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190122013713-64072686203f/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480 h1:O5YqonU5IWby+w98jVUG9h7zlCWCcH4RHyPVReBmhzk=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190422183909-d864b10871cd/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443 h1:IcSOAf4PyMp3U3XbIEj1/xJ2BjNN2jWv7JoyOsMxXUU=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190618222545-ea8f1a30c443/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472 h1:Gv7RPwsi3eZ2Fgewe3CBsuOebPwO27PoXzRpJPsvSSM=
 | 
			
		||||
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
			
		||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
 | 
			
		||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
 | 
			
		||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
 | 
			
		||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
 | 
			
		||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 | 
			
		||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 | 
			
		||||
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 | 
			
		||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
 | 
			
		||||
golang.org/x/mobile v0.0.0-20190814143026-e8b3e6111d02/go.mod h1:z5wpDCy2wbnXyFdvEuY3LhY9gBUL86/IOILm+Hsjx+E=
 | 
			
		||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
 | 
			
		||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
 | 
			
		||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
			
		||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190320064053-1272bf9dcd53/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190502183928-7f726cade0ab/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
			
		||||
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 | 
			
		||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 | 
			
		||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980 h1:dfGZHvZk057jK2MCeWus/TowKpJ8y4AmooUzdBSR9GU=
 | 
			
		||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297 h1:k7pJ2yAPLPgbskkFdhRCsA77k2fySZ1zf2zCjvQCiIM=
 | 
			
		||||
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180620175406-ef147856a6dd/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759 h1:TMrx+Qdx7uJAeUbv15N72h5Hmyb5+VDjEiMufAEAM04=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20181101160152-c453e0c75759/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 h1:SVwTIAaPC2U/AvvLNZ2a7OVsmBpC8L5BlwK1whH3hm0=
 | 
			
		||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
 | 
			
		||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA=
 | 
			
		||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
 | 
			
		||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180824143301-4910a1d54f87/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
@@ -391,24 +650,74 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h
 | 
			
		||||
golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223 h1:DH4skfRX4EBpamg7iV4ZlCpblAHI6s6TDM39bFZumv8=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190321052220-f7bb7a8bee54/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e h1:nFYrTHrdrAOpShe27kaFHjsqYSEQ0KWqdWLu3xuZJts=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f h1:dHNZYIYdq2QuU6w73vZ/DzesPbVlZVYZTtTZmrnsbQ8=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190618155005-516e3c20635f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd h1:DBH9mDw0zluJT/R+nGuV3jWFWLFaHyYZWD4tOT+cjn0=
 | 
			
		||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
			
		||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
 | 
			
		||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
			
		||||
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
 | 
			
		||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
			
		||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190618163018-fdf1049a943a h1:aQmaYPOmKItb96VioBrTlYay5tSNUdKAFEhPCWMeLSM=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190618163018-fdf1049a943a/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190617190820-da514acc4774/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190808195139-e713427fea3f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190820033707-85edb9ef3283/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190903163617-be0da057c5e3 h1:1cLrGl9PL64Mzl9NATDCqFE57dVYwWOkoPXvppEnjO4=
 | 
			
		||||
golang.org/x/tools v0.0.0-20190903163617-be0da057c5e3/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
			
		||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
			
		||||
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
 | 
			
		||||
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
 | 
			
		||||
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
 | 
			
		||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 | 
			
		||||
google.golang.org/appengine v1.2.0 h1:S0iUepdCWODXRvtE+gcRDd15L+k+k1AiHlMiMjefH24=
 | 
			
		||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
			
		||||
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
 | 
			
		||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
			
		||||
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
 | 
			
		||||
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 | 
			
		||||
google.golang.org/appengine v1.6.2 h1:j8RI1yW0SkI+paT6uGwMlrMI/6zwYA6/CFil8rxOzGI=
 | 
			
		||||
google.golang.org/appengine v1.6.2/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 | 
			
		||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
 | 
			
		||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
 | 
			
		||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
 | 
			
		||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 | 
			
		||||
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
 | 
			
		||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
 | 
			
		||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 | 
			
		||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
 | 
			
		||||
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
 | 
			
		||||
@@ -419,20 +728,27 @@ gopkg.in/bufio.v1 v1.0.0-20140618132640-567b2bfa514e/go.mod h1:xsQCaysVCudhrYTfz
 | 
			
		||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0 h1:CO465/foR4+bY1xNYjZEl6l8By1g/iMsImoruxfEt84=
 | 
			
		||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.2.0/go.mod h1:s2mQFI9McjArkyCwyEwU//+luQENTnD/Lfb/7Sj3/kQ=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
 | 
			
		||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
			
		||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0 h1:oxOEwvhxLMpWpN+0pb2r9TWrM0DCFBHxbuIlS27tmFg=
 | 
			
		||||
gopkg.in/editorconfig/editorconfig-core-go.v1 v1.3.0/go.mod h1:s2mQFI9McjArkyCwyEwU//+luQENTnD/Lfb/7Sj3/kQ=
 | 
			
		||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 | 
			
		||||
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
 | 
			
		||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
 | 
			
		||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
 | 
			
		||||
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
 | 
			
		||||
gopkg.in/ini.v1 v1.42.0 h1:7N3gPTt50s8GuLortA00n8AqRTk75qOP98+mTPpgzRk=
 | 
			
		||||
gopkg.in/ini.v1 v1.42.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/ini.v1 v1.46.0 h1:VeDZbLYGaupuvIrsYCEOe/L/2Pcs5n7hdO1ZTjporag=
 | 
			
		||||
gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
			
		||||
gopkg.in/ldap.v3 v3.0.2 h1:R6RBtabK6e1GO0eQKtkyOFbAHO73QesLzI2w2DZ6b9w=
 | 
			
		||||
gopkg.in/ldap.v3 v3.0.2/go.mod h1:oxD7NyBuxchC+SgJDE1Q5Od05eGt29SDQVBmV+HYbzw=
 | 
			
		||||
gopkg.in/macaron.v1 v1.3.2 h1:AvWIaPmwBUA87/OWzePkoxeaw6YJWDfBt1pDFPBnLf8=
 | 
			
		||||
gopkg.in/macaron.v1 v1.3.2/go.mod h1:PrsiawTWAGZs6wFbT5hlr7SQ2Ns9h7cUVtcUu4lQOVo=
 | 
			
		||||
gopkg.in/redis.v2 v2.3.2 h1:GPVIIB/JnL1wvfULefy3qXmPu1nfNu2d0yA09FHgwfs=
 | 
			
		||||
gopkg.in/redis.v2 v2.3.2/go.mod h1:4wl9PJ/CqzeHk3LVq1hNLHH8krm3+AXEgut4jVc++LU=
 | 
			
		||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 | 
			
		||||
gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
 | 
			
		||||
gopkg.in/src-d/go-billy.v4 v4.3.0 h1:KtlZ4c1OWbIs4jCv5ZXrTqG8EQocr0g/d4DjNg70aek=
 | 
			
		||||
gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk=
 | 
			
		||||
gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg=
 | 
			
		||||
@@ -447,12 +763,19 @@ gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkep
 | 
			
		||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
 | 
			
		||||
gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME=
 | 
			
		||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
 | 
			
		||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
 | 
			
		||||
honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
 | 
			
		||||
mvdan.cc/xurls/v2 v2.0.0 h1:r1zSOSNS/kqtpmATyMMMvaZ4/djsesbYz5kr0+qMRWc=
 | 
			
		||||
mvdan.cc/xurls/v2 v2.0.0/go.mod h1:2/webFPYOXN9jp/lzuj0zuAVlF+9g4KPFJANH1oJhRU=
 | 
			
		||||
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
 | 
			
		||||
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a h1:8q33ShxKXRwQ7JVd1ZnhIU3hZhwwn0Le+4fTeAackuM=
 | 
			
		||||
strk.kbt.io/projects/go/libravatar v0.0.0-20160628055650-5eed7bff870a/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
 | 
			
		||||
xorm.io/builder v0.3.5 h1:EilU39fvWDxjb1cDaELpYhsF+zziRBhew8xk4pngO+A=
 | 
			
		||||
 
 | 
			
		||||
@@ -51,6 +51,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	err = gitRepo.CreateTag("v0.0.1", "master")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
@@ -112,6 +113,7 @@ func TestAPICreateReleaseToDefaultBranchOnExistingTag(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	err = gitRepo.CreateTag("v0.0.1", "master")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -139,6 +139,7 @@ func TestAPICreateFile(t *testing.T) {
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
 | 
			
		||||
			gitRepo.Close()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Test creating a file in a new branch
 | 
			
		||||
 
 | 
			
		||||
@@ -143,6 +143,7 @@ func TestAPIUpdateFile(t *testing.T) {
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, fileResponse.Commit.HTMLURL)
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, fileResponse.Commit.Author.Email)
 | 
			
		||||
			assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, fileResponse.Commit.Author.Name)
 | 
			
		||||
			gitRepo.Close()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Test updating a file in a new branch
 | 
			
		||||
 
 | 
			
		||||
@@ -74,6 +74,8 @@ func testAPIGetContentsList(t *testing.T, u *url.URL) {
 | 
			
		||||
	repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	// Get the commit ID of the default branch
 | 
			
		||||
	gitRepo, _ := git.OpenRepository(repo1.RepoPath())
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
 | 
			
		||||
	// Make a new tag in repo1
 | 
			
		||||
	newTag := "test_tag"
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,8 @@ func testAPIGetContents(t *testing.T, u *url.URL) {
 | 
			
		||||
	repo1.CreateNewBranch(user2, repo1.DefaultBranch, newBranch)
 | 
			
		||||
	// Get the commit ID of the default branch
 | 
			
		||||
	gitRepo, _ := git.OpenRepository(repo1.RepoPath())
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	commitID, _ := gitRepo.GetBranchCommitID(repo1.DefaultBranch)
 | 
			
		||||
	// Make a new tag in repo1
 | 
			
		||||
	newTag := "test_tag"
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,8 @@ func TestAPIGitTags(t *testing.T) {
 | 
			
		||||
	git.NewCommand("config", "user.email", user.Email).RunInDir(repo.RepoPath())
 | 
			
		||||
 | 
			
		||||
	gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	commit, _ := gitRepo.GetBranchCommit("master")
 | 
			
		||||
	lTagName := "lightweightTag"
 | 
			
		||||
	gitRepo.CreateTag(lTagName, commit.ID.String())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										35
									
								
								integrations/api_team_user_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								integrations/api_team_user_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,35 @@
 | 
			
		||||
// Copyright 2019 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 integrations
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
	"code.gitea.io/gitea/routers/api/v1/convert"
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func TestAPITeamUser(t *testing.T) {
 | 
			
		||||
	prepareTestEnv(t)
 | 
			
		||||
 | 
			
		||||
	normalUsername := "user2"
 | 
			
		||||
	session := loginUser(t, normalUsername)
 | 
			
		||||
	token := getTokenForLoggedInUser(t, session)
 | 
			
		||||
	req := NewRequest(t, "GET", "/api/v1/teams/1/members/user1?token="+token)
 | 
			
		||||
	session.MakeRequest(t, req, http.StatusNotFound)
 | 
			
		||||
 | 
			
		||||
	req = NewRequest(t, "GET", "/api/v1/teams/1/members/user2?token="+token)
 | 
			
		||||
	resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
	var user2 *api.User
 | 
			
		||||
	DecodeJSON(t, resp, &user2)
 | 
			
		||||
	user2.Created = user2.Created.In(time.Local)
 | 
			
		||||
	user := models.AssertExistsAndLoadBean(t, &models.User{Name: "user2"}).(*models.User)
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, convert.ToUser(user, true, false), user2)
 | 
			
		||||
}
 | 
			
		||||
@@ -24,7 +24,7 @@ func TestUserHeatmap(t *testing.T) {
 | 
			
		||||
	var heatmap []*models.UserHeatmapData
 | 
			
		||||
	DecodeJSON(t, resp, &heatmap)
 | 
			
		||||
	var dummyheatmap []*models.UserHeatmapData
 | 
			
		||||
	dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1540080000, Contributions: 1})
 | 
			
		||||
	dummyheatmap = append(dummyheatmap, &models.UserHeatmapData{Timestamp: 1571616000, Contributions: 1})
 | 
			
		||||
 | 
			
		||||
	assert.Equal(t, dummyheatmap, heatmap)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,9 @@ import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
	"path"
 | 
			
		||||
	"path/filepath"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"testing"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
@@ -36,7 +38,12 @@ func withKeyFile(t *testing.T, keyname string, callback func(string)) {
 | 
			
		||||
	err = ssh.GenKeyPair(keyFile)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	err = ioutil.WriteFile(path.Join(tmpDir, "ssh"), []byte("#!/bin/bash\n"+
 | 
			
		||||
		"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\" \"$@\""), 0700)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
	//Setup ssh wrapper
 | 
			
		||||
	os.Setenv("GIT_SSH", path.Join(tmpDir, "ssh"))
 | 
			
		||||
	os.Setenv("GIT_SSH_COMMAND",
 | 
			
		||||
		"ssh -o \"UserKnownHostsFile=/dev/null\" -o \"StrictHostKeyChecking=no\" -o \"IdentitiesOnly=yes\" -i \""+keyFile+"\"")
 | 
			
		||||
	os.Setenv("GIT_SSH_VARIANT", "ssh")
 | 
			
		||||
@@ -53,6 +60,24 @@ func createSSHUrl(gitPath string, u *url.URL) *url.URL {
 | 
			
		||||
	return &u2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func allowLFSFilters() []string {
 | 
			
		||||
	// Now here we should explicitly allow lfs filters to run
 | 
			
		||||
	globalArgs := git.GlobalCommandArgs
 | 
			
		||||
	filteredLFSGlobalArgs := make([]string, len(git.GlobalCommandArgs))
 | 
			
		||||
	j := 0
 | 
			
		||||
	for _, arg := range git.GlobalCommandArgs {
 | 
			
		||||
		if strings.Contains(arg, "lfs") {
 | 
			
		||||
			j--
 | 
			
		||||
		} else {
 | 
			
		||||
			filteredLFSGlobalArgs[j] = arg
 | 
			
		||||
			j++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	filteredLFSGlobalArgs = filteredLFSGlobalArgs[:j]
 | 
			
		||||
	git.GlobalCommandArgs = filteredLFSGlobalArgs
 | 
			
		||||
	return globalArgs
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
 | 
			
		||||
	prepareTestEnv(t, 1)
 | 
			
		||||
	s := http.Server{
 | 
			
		||||
@@ -78,7 +103,9 @@ func onGiteaRun(t *testing.T, callback func(*testing.T, *url.URL)) {
 | 
			
		||||
 | 
			
		||||
func doGitClone(dstLocalPath string, u *url.URL) func(*testing.T) {
 | 
			
		||||
	return func(t *testing.T) {
 | 
			
		||||
		oldGlobals := allowLFSFilters()
 | 
			
		||||
		assert.NoError(t, git.Clone(u.String(), dstLocalPath, git.CloneRepoOptions{}))
 | 
			
		||||
		git.GlobalCommandArgs = oldGlobals
 | 
			
		||||
		assert.True(t, com.IsExist(filepath.Join(dstLocalPath, "README.md")))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -139,7 +166,9 @@ func doGitCreateBranch(dstPath, branch string) func(*testing.T) {
 | 
			
		||||
 | 
			
		||||
func doGitCheckoutBranch(dstPath string, args ...string) func(*testing.T) {
 | 
			
		||||
	return func(t *testing.T) {
 | 
			
		||||
		oldGlobals := allowLFSFilters()
 | 
			
		||||
		_, err := git.NewCommand(append([]string{"checkout"}, args...)...).RunInDir(dstPath)
 | 
			
		||||
		git.GlobalCommandArgs = oldGlobals
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -153,7 +182,9 @@ func doGitMerge(dstPath string, args ...string) func(*testing.T) {
 | 
			
		||||
 | 
			
		||||
func doGitPull(dstPath string, args ...string) func(*testing.T) {
 | 
			
		||||
	return func(t *testing.T) {
 | 
			
		||||
		oldGlobals := allowLFSFilters()
 | 
			
		||||
		_, err := git.NewCommand(append([]string{"pull"}, args...)...).RunInDir(dstPath)
 | 
			
		||||
		git.GlobalCommandArgs = oldGlobals
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@ import (
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/models"
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
	api "code.gitea.io/gitea/modules/structs"
 | 
			
		||||
 | 
			
		||||
	"github.com/stretchr/testify/assert"
 | 
			
		||||
@@ -135,6 +136,11 @@ func standardCommitAndPushTest(t *testing.T, dstPath string) (little, big string
 | 
			
		||||
func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS string) {
 | 
			
		||||
	t.Run("LFS", func(t *testing.T) {
 | 
			
		||||
		PrintCurrentTest(t)
 | 
			
		||||
		setting.CheckLFSVersion()
 | 
			
		||||
		if !setting.LFS.StartServer {
 | 
			
		||||
			t.Skip()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		prefix := "lfs-data-file-"
 | 
			
		||||
		_, err := git.NewCommand("lfs").AddArguments("install").RunInDir(dstPath)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
@@ -142,6 +148,21 @@ func lfsCommitAndPushTest(t *testing.T, dstPath string) (littleLFS, bigLFS strin
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		err = git.AddChanges(dstPath, false, ".gitattributes")
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		oldGlobals := allowLFSFilters()
 | 
			
		||||
		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: fmt.Sprintf("Testing commit @ %v", time.Now()),
 | 
			
		||||
		})
 | 
			
		||||
		git.GlobalCommandArgs = oldGlobals
 | 
			
		||||
 | 
			
		||||
		littleLFS, bigLFS = commitAndPushTest(t, dstPath, prefix)
 | 
			
		||||
 | 
			
		||||
@@ -185,20 +206,25 @@ func rawTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS s
 | 
			
		||||
		resp := session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
		assert.Equal(t, littleSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
		req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
 | 
			
		||||
		resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
		assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
			
		||||
		assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
		setting.CheckLFSVersion()
 | 
			
		||||
		if setting.LFS.StartServer {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", littleLFS))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
			
		||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !testing.Short() {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", big))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Body.Len())
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", bigLFS))
 | 
			
		||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
			assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
			if setting.LFS.StartServer {
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/", username, reponame, "/raw/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
			
		||||
				assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
			
		||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -217,18 +243,23 @@ func mediaTest(t *testing.T, ctx *APITestContext, little, big, littleLFS, bigLFS
 | 
			
		||||
		resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
		assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
		req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", littleLFS))
 | 
			
		||||
		resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
		assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
		setting.CheckLFSVersion()
 | 
			
		||||
		if setting.LFS.StartServer {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", littleLFS))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, littleSize, resp.Length)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if !testing.Short() {
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", big))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
 | 
			
		||||
			req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", bigLFS))
 | 
			
		||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
			assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
			if setting.LFS.StartServer {
 | 
			
		||||
				req = NewRequest(t, "GET", path.Join("/", username, reponame, "/media/branch/master/", bigLFS))
 | 
			
		||||
				resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
			
		||||
				assert.Equal(t, bigSize, resp.Length)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
@@ -274,6 +305,8 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	//Commit
 | 
			
		||||
	// Now here we should explicitly allow lfs filters to run
 | 
			
		||||
	oldGlobals := allowLFSFilters()
 | 
			
		||||
	err = git.AddChanges(repoPath, false, filepath.Base(tmpFile.Name()))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
@@ -291,6 +324,7 @@ func generateCommitWithNewData(size int, repoPath, email, fullName, prefix strin
 | 
			
		||||
		},
 | 
			
		||||
		Message: fmt.Sprintf("Testing commit @ %v", time.Now()),
 | 
			
		||||
	})
 | 
			
		||||
	git.GlobalCommandArgs = oldGlobals
 | 
			
		||||
	return filepath.Base(tmpFile.Name()), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,11 @@ func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string
 | 
			
		||||
 | 
			
		||||
func doLfs(t *testing.T, content *[]byte, expectGzip bool) {
 | 
			
		||||
	prepareTestEnv(t)
 | 
			
		||||
	setting.CheckLFSVersion()
 | 
			
		||||
	if !setting.LFS.StartServer {
 | 
			
		||||
		t.Skip()
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	repo, err := models.GetRepositoryByOwnerAndName("user2", "repo1")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	oid := storeObjectInRepo(t, repo.ID, content)
 | 
			
		||||
 
 | 
			
		||||
@@ -73,6 +73,7 @@ func testDeleteRepoFile(t *testing.T, u *url.URL) {
 | 
			
		||||
	test.LoadRepoCommit(t, ctx)
 | 
			
		||||
	test.LoadUser(t, ctx, 2)
 | 
			
		||||
	test.LoadGitRepo(t, ctx)
 | 
			
		||||
	defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
	repo := ctx.Repo.Repository
 | 
			
		||||
	doer := ctx.User
 | 
			
		||||
	opts := getDeleteRepoFileOptions(repo)
 | 
			
		||||
@@ -111,6 +112,8 @@ func testDeleteRepoFileWithoutBranchNames(t *testing.T, u *url.URL) {
 | 
			
		||||
	test.LoadRepoCommit(t, ctx)
 | 
			
		||||
	test.LoadUser(t, ctx, 2)
 | 
			
		||||
	test.LoadGitRepo(t, ctx)
 | 
			
		||||
	defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	repo := ctx.Repo.Repository
 | 
			
		||||
	doer := ctx.User
 | 
			
		||||
	opts := getDeleteRepoFileOptions(repo)
 | 
			
		||||
@@ -139,6 +142,8 @@ func TestDeleteRepoFileErrors(t *testing.T) {
 | 
			
		||||
	test.LoadRepoCommit(t, ctx)
 | 
			
		||||
	test.LoadUser(t, ctx, 2)
 | 
			
		||||
	test.LoadGitRepo(t, ctx)
 | 
			
		||||
	defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	repo := ctx.Repo.Repository
 | 
			
		||||
	doer := ctx.User
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -191,6 +191,8 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
 | 
			
		||||
		test.LoadRepoCommit(t, ctx)
 | 
			
		||||
		test.LoadUser(t, ctx, 2)
 | 
			
		||||
		test.LoadGitRepo(t, ctx)
 | 
			
		||||
		defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		repo := ctx.Repo.Repository
 | 
			
		||||
		doer := ctx.User
 | 
			
		||||
		opts := getCreateRepoFileOptions(repo)
 | 
			
		||||
@@ -201,6 +203,8 @@ func TestCreateOrUpdateRepoFileForCreate(t *testing.T) {
 | 
			
		||||
		// asserts
 | 
			
		||||
		assert.Nil(t, err)
 | 
			
		||||
		gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
		defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
 | 
			
		||||
		expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID)
 | 
			
		||||
		assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
 | 
			
		||||
@@ -220,6 +224,8 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
 | 
			
		||||
		test.LoadRepoCommit(t, ctx)
 | 
			
		||||
		test.LoadUser(t, ctx, 2)
 | 
			
		||||
		test.LoadGitRepo(t, ctx)
 | 
			
		||||
		defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		repo := ctx.Repo.Repository
 | 
			
		||||
		doer := ctx.User
 | 
			
		||||
		opts := getUpdateRepoFileOptions(repo)
 | 
			
		||||
@@ -230,6 +236,8 @@ func TestCreateOrUpdateRepoFileForUpdate(t *testing.T) {
 | 
			
		||||
		// asserts
 | 
			
		||||
		assert.Nil(t, err)
 | 
			
		||||
		gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
		defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch)
 | 
			
		||||
		expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath)
 | 
			
		||||
		assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
 | 
			
		||||
@@ -249,6 +257,8 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
 | 
			
		||||
		test.LoadRepoCommit(t, ctx)
 | 
			
		||||
		test.LoadUser(t, ctx, 2)
 | 
			
		||||
		test.LoadGitRepo(t, ctx)
 | 
			
		||||
		defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		repo := ctx.Repo.Repository
 | 
			
		||||
		doer := ctx.User
 | 
			
		||||
		opts := getUpdateRepoFileOptions(repo)
 | 
			
		||||
@@ -261,6 +271,8 @@ func TestCreateOrUpdateRepoFileForUpdateWithFileMove(t *testing.T) {
 | 
			
		||||
		// asserts
 | 
			
		||||
		assert.Nil(t, err)
 | 
			
		||||
		gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
		defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		commit, _ := gitRepo.GetBranchCommit(opts.NewBranch)
 | 
			
		||||
		expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.TreePath)
 | 
			
		||||
		// assert that the old file no longer exists in the last commit of the branch
 | 
			
		||||
@@ -288,6 +300,8 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
 | 
			
		||||
		test.LoadRepoCommit(t, ctx)
 | 
			
		||||
		test.LoadUser(t, ctx, 2)
 | 
			
		||||
		test.LoadGitRepo(t, ctx)
 | 
			
		||||
		defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		repo := ctx.Repo.Repository
 | 
			
		||||
		doer := ctx.User
 | 
			
		||||
		opts := getUpdateRepoFileOptions(repo)
 | 
			
		||||
@@ -300,6 +314,8 @@ func TestCreateOrUpdateRepoFileWithoutBranchNames(t *testing.T) {
 | 
			
		||||
		// asserts
 | 
			
		||||
		assert.Nil(t, err)
 | 
			
		||||
		gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
			
		||||
		defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		commitID, _ := gitRepo.GetBranchCommitID(repo.DefaultBranch)
 | 
			
		||||
		expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commitID, opts.TreePath)
 | 
			
		||||
		assert.EqualValues(t, expectedFileResponse.Content, fileResponse.Content)
 | 
			
		||||
@@ -315,6 +331,8 @@ func TestCreateOrUpdateRepoFileErrors(t *testing.T) {
 | 
			
		||||
		test.LoadRepoCommit(t, ctx)
 | 
			
		||||
		test.LoadUser(t, ctx, 2)
 | 
			
		||||
		test.LoadGitRepo(t, ctx)
 | 
			
		||||
		defer ctx.Repo.GitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		repo := ctx.Repo.Repository
 | 
			
		||||
		doer := ctx.User
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -10,6 +10,7 @@ import (
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"sync"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
@@ -25,11 +26,21 @@ type TestLogger struct {
 | 
			
		||||
var writerCloser = &testLoggerWriterCloser{}
 | 
			
		||||
 | 
			
		||||
type testLoggerWriterCloser struct {
 | 
			
		||||
	sync.RWMutex
 | 
			
		||||
	t testing.TB
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *testLoggerWriterCloser) setT(t *testing.TB) {
 | 
			
		||||
	w.Lock()
 | 
			
		||||
	w.t = *t
 | 
			
		||||
	w.Unlock()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (w *testLoggerWriterCloser) Write(p []byte) (int, error) {
 | 
			
		||||
	if w.t != nil {
 | 
			
		||||
	w.RLock()
 | 
			
		||||
	t := w.t
 | 
			
		||||
	w.RUnlock()
 | 
			
		||||
	if t != nil {
 | 
			
		||||
		if len(p) > 0 && p[len(p)-1] == '\n' {
 | 
			
		||||
			p = p[:len(p)-1]
 | 
			
		||||
		}
 | 
			
		||||
@@ -54,7 +65,7 @@ func (w *testLoggerWriterCloser) Write(p []byte) (int, error) {
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
 | 
			
		||||
		w.t.Log(string(p))
 | 
			
		||||
		t.Log(string(p))
 | 
			
		||||
		return len(p), nil
 | 
			
		||||
	}
 | 
			
		||||
	return len(p), nil
 | 
			
		||||
@@ -77,7 +88,7 @@ func PrintCurrentTest(t testing.TB, skip ...int) {
 | 
			
		||||
	} else {
 | 
			
		||||
		fmt.Fprintf(os.Stdout, "=== %s (%s:%d)\n", t.Name(), strings.TrimPrefix(filename, prefix), line)
 | 
			
		||||
	}
 | 
			
		||||
	writerCloser.t = t
 | 
			
		||||
	writerCloser.setT(&t)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Printf takes a format and args and prints the string to os.Stdout
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ var (
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const issueRefRegexpStr = `(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)+`
 | 
			
		||||
const issueRefRegexpStrNoKeyword = `(?:\s|^|\(|\[)(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)(?:\s|$|\)|\]|\.(\s|$))`
 | 
			
		||||
const issueRefRegexpStrNoKeyword = `(?:\s|^|\(|\[)(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)(?:\s|$|\)|\]|:|\.(\s|$))`
 | 
			
		||||
 | 
			
		||||
func assembleKeywordsPattern(words []string) string {
 | 
			
		||||
	return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
 | 
			
		||||
@@ -762,6 +762,7 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Error("GetBranchCommitID[%s]: %v", opts.RefFullName, err)
 | 
			
		||||
			}
 | 
			
		||||
			gitRepo.Close()
 | 
			
		||||
			if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
 | 
			
		||||
				Ref:     refName,
 | 
			
		||||
				Sha:     shaSum,
 | 
			
		||||
@@ -797,6 +798,8 @@ func CommitRepoAction(opts CommitRepoActionOptions) error {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("GetTagCommitID[%s]: %v", opts.RefFullName, err)
 | 
			
		||||
		}
 | 
			
		||||
		gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		if err = PrepareWebhooks(repo, HookEventCreate, &api.CreatePayload{
 | 
			
		||||
			Ref:     refName,
 | 
			
		||||
			Sha:     shaSum,
 | 
			
		||||
 
 | 
			
		||||
@@ -160,6 +160,7 @@ func TestRegExp_issueReferenceKeywordsPat(t *testing.T) {
 | 
			
		||||
		"#2",
 | 
			
		||||
		"[#2]",
 | 
			
		||||
		"please see go-gitea/gitea#5",
 | 
			
		||||
		"#2:",
 | 
			
		||||
	}
 | 
			
		||||
	falseTestCases := []string{
 | 
			
		||||
		"kb#2",
 | 
			
		||||
 
 | 
			
		||||
@@ -192,7 +192,7 @@ func UpdateProtectBranch(repo *Repository, protectBranch *ProtectedBranch, opts
 | 
			
		||||
	}
 | 
			
		||||
	protectBranch.MergeWhitelistUserIDs = whitelist
 | 
			
		||||
 | 
			
		||||
	whitelist, err = updateUserWhitelist(repo, protectBranch.ApprovalsWhitelistUserIDs, opts.ApprovalsUserIDs)
 | 
			
		||||
	whitelist, err = updateApprovalWhitelist(repo, protectBranch.ApprovalsWhitelistUserIDs, opts.ApprovalsUserIDs)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -298,6 +298,27 @@ func (repo *Repository) IsProtectedBranchForMerging(pr *PullRequest, branchName
 | 
			
		||||
	return false, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// updateApprovalWhitelist checks whether the user whitelist changed and returns a whitelist with
 | 
			
		||||
// the users from newWhitelist which have explicit read or write access to the repo.
 | 
			
		||||
func updateApprovalWhitelist(repo *Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
 | 
			
		||||
	hasUsersChanged := !util.IsSliceInt64Eq(currentWhitelist, newWhitelist)
 | 
			
		||||
	if !hasUsersChanged {
 | 
			
		||||
		return currentWhitelist, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	whitelist = make([]int64, 0, len(newWhitelist))
 | 
			
		||||
	for _, userID := range newWhitelist {
 | 
			
		||||
		if reader, err := repo.IsReader(userID); err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		} else if !reader {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		whitelist = append(whitelist, userID)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// updateUserWhitelist checks whether the user whitelist changed and returns a whitelist with
 | 
			
		||||
// the users from newWhitelist which have write access to the repo.
 | 
			
		||||
func updateUserWhitelist(repo *Repository, currentWhitelist, newWhitelist []int64) (whitelist []int64, err error) {
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
  act_user_id: 2
 | 
			
		||||
  repo_id: 2
 | 
			
		||||
  is_private: true
 | 
			
		||||
  created_unix: 1540139562
 | 
			
		||||
  created_unix: 1571686356
 | 
			
		||||
 | 
			
		||||
-
 | 
			
		||||
  id: 2
 | 
			
		||||
 
 | 
			
		||||
@@ -675,6 +675,7 @@ func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := gitRepo.GetCommit(afterCommitID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -747,6 +748,7 @@ func GetRawDiffForFile(repoPath, startCommit, endCommit string, diffType RawDiff
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := repo.GetCommit(endCommit)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ func BenchmarkGetCommitGraph(b *testing.B) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Error("Could not open repository")
 | 
			
		||||
	}
 | 
			
		||||
	defer currentRepo.Close()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		graph, err := GetCommitGraph(currentRepo)
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										165
									
								
								models/issue.go
									
									
									
									
									
								
							
							
						
						
									
										165
									
								
								models/issue.go
									
									
									
									
									
								
							@@ -755,7 +755,7 @@ func (issue *Issue) changeStatus(e *xorm.Session, doer *User, isClosed bool) (er
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update issue count of milestone
 | 
			
		||||
	if err = changeMilestoneIssueStats(e, issue); err != nil {
 | 
			
		||||
	if err := updateMilestoneClosedNum(e, issue.MilestoneID); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1099,7 +1099,11 @@ func newIssue(e *xorm.Session, doer *User, opts NewIssueOptions) (err error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.Issue.MilestoneID > 0 {
 | 
			
		||||
		if err = changeMilestoneAssign(e, doer, opts.Issue, -1); err != nil {
 | 
			
		||||
		if _, err = e.Exec("UPDATE `milestone` SET num_issues=num_issues+1 WHERE id=?", opts.Issue.MilestoneID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, err = createMilestoneComment(e, doer, opts.Repo, opts.Issue, 0, opts.Issue.MilestoneID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
@@ -1446,7 +1450,7 @@ func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
 | 
			
		||||
	userIDs := make([]int64, 0, 5)
 | 
			
		||||
	if err := e.Table("comment").Cols("poster_id").
 | 
			
		||||
		Where("`comment`.issue_id = ?", issueID).
 | 
			
		||||
		And("`comment`.type = ?", CommentTypeComment).
 | 
			
		||||
		And("`comment`.type in (?,?,?)", CommentTypeComment, CommentTypeCode, CommentTypeReview).
 | 
			
		||||
		And("`user`.is_active = ?", true).
 | 
			
		||||
		And("`user`.prohibit_login = ?", false).
 | 
			
		||||
		Join("INNER", "`user`", "`user`.id = `comment`.poster_id").
 | 
			
		||||
@@ -1462,46 +1466,18 @@ func getParticipantsByIssueID(e Engine, issueID int64) ([]*User, error) {
 | 
			
		||||
	return users, e.In("id", userIDs).Find(&users)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateIssueMentions extracts mentioned people from content and
 | 
			
		||||
// updates issue-user relations for them.
 | 
			
		||||
func UpdateIssueMentions(e Engine, issueID int64, mentions []string) error {
 | 
			
		||||
// UpdateIssueMentions updates issue-user relations for mentioned users.
 | 
			
		||||
func UpdateIssueMentions(e Engine, issueID int64, mentions []*User) error {
 | 
			
		||||
	if len(mentions) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for i := range mentions {
 | 
			
		||||
		mentions[i] = strings.ToLower(mentions[i])
 | 
			
		||||
	ids := make([]int64, len(mentions))
 | 
			
		||||
	for i, u := range mentions {
 | 
			
		||||
		ids[i] = u.ID
 | 
			
		||||
	}
 | 
			
		||||
	users := make([]*User, 0, len(mentions))
 | 
			
		||||
 | 
			
		||||
	if err := e.In("lower_name", mentions).Asc("lower_name").Find(&users); err != nil {
 | 
			
		||||
		return fmt.Errorf("find mentioned users: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ids := make([]int64, 0, len(mentions))
 | 
			
		||||
	for _, user := range users {
 | 
			
		||||
		ids = append(ids, user.ID)
 | 
			
		||||
		if !user.IsOrganization() || user.NumMembers == 0 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memberIDs := make([]int64, 0, user.NumMembers)
 | 
			
		||||
		orgUsers, err := getOrgUsersByOrgID(e, user.ID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return fmt.Errorf("GetOrgUsersByOrgID [%d]: %v", user.ID, err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, orgUser := range orgUsers {
 | 
			
		||||
			memberIDs = append(memberIDs, orgUser.ID)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ids = append(ids, memberIDs...)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := UpdateIssueUsersByMentions(e, issueID, ids); err != nil {
 | 
			
		||||
		return fmt.Errorf("UpdateIssueUsersByMentions: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1854,3 +1830,120 @@ func (issue *Issue) updateClosedNum(e Engine) (err error) {
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ResolveMentionsByVisibility returns the users mentioned in an issue, removing those that
 | 
			
		||||
// don't have access to reading it. Teams are expanded into their users, but organizations are ignored.
 | 
			
		||||
func (issue *Issue) ResolveMentionsByVisibility(e Engine, doer *User, mentions []string) (users []*User, err error) {
 | 
			
		||||
	if len(mentions) == 0 {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err = issue.loadRepo(e); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	resolved := make(map[string]bool, 20)
 | 
			
		||||
	names := make([]string, 0, 20)
 | 
			
		||||
	resolved[doer.LowerName] = true
 | 
			
		||||
	for _, name := range mentions {
 | 
			
		||||
		name := strings.ToLower(name)
 | 
			
		||||
		if _, ok := resolved[name]; ok {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		resolved[name] = false
 | 
			
		||||
		names = append(names, name)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := issue.Repo.getOwner(e); err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if issue.Repo.Owner.IsOrganization() {
 | 
			
		||||
		// Since there can be users with names that match the name of a team,
 | 
			
		||||
		// if the team exists and can read the issue, the team takes precedence.
 | 
			
		||||
		teams := make([]*Team, 0, len(names))
 | 
			
		||||
		if err := e.
 | 
			
		||||
			Join("INNER", "team_repo", "team_repo.team_id = team.id").
 | 
			
		||||
			Where("team_repo.repo_id=?", issue.Repo.ID).
 | 
			
		||||
			In("team.lower_name", names).
 | 
			
		||||
			Find(&teams); err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("find mentioned teams: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		if len(teams) != 0 {
 | 
			
		||||
			checked := make([]int64, 0, len(teams))
 | 
			
		||||
			unittype := UnitTypeIssues
 | 
			
		||||
			if issue.IsPull {
 | 
			
		||||
				unittype = UnitTypePullRequests
 | 
			
		||||
			}
 | 
			
		||||
			for _, team := range teams {
 | 
			
		||||
				if team.Authorize >= AccessModeOwner {
 | 
			
		||||
					checked = append(checked, team.ID)
 | 
			
		||||
					resolved[team.LowerName] = true
 | 
			
		||||
					continue
 | 
			
		||||
				}
 | 
			
		||||
				has, err := e.Get(&TeamUnit{OrgID: issue.Repo.Owner.ID, TeamID: team.ID, Type: unittype})
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return nil, fmt.Errorf("get team units (%d): %v", team.ID, err)
 | 
			
		||||
				}
 | 
			
		||||
				if has {
 | 
			
		||||
					checked = append(checked, team.ID)
 | 
			
		||||
					resolved[team.LowerName] = true
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if len(checked) != 0 {
 | 
			
		||||
				teamusers := make([]*User, 0, 20)
 | 
			
		||||
				if err := e.
 | 
			
		||||
					Join("INNER", "team_user", "team_user.uid = `user`.id").
 | 
			
		||||
					In("`team_user`.team_id", checked).
 | 
			
		||||
					And("`user`.is_active = ?", true).
 | 
			
		||||
					And("`user`.prohibit_login = ?", false).
 | 
			
		||||
					Find(&teamusers); err != nil {
 | 
			
		||||
					return nil, fmt.Errorf("get teams users: %v", err)
 | 
			
		||||
				}
 | 
			
		||||
				if len(teamusers) > 0 {
 | 
			
		||||
					users = make([]*User, 0, len(teamusers))
 | 
			
		||||
					for _, user := range teamusers {
 | 
			
		||||
						if already, ok := resolved[user.LowerName]; !ok || !already {
 | 
			
		||||
							users = append(users, user)
 | 
			
		||||
							resolved[user.LowerName] = true
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Remove names already in the list to avoid querying the database if pending names remain
 | 
			
		||||
		names = make([]string, 0, len(resolved))
 | 
			
		||||
		for name, already := range resolved {
 | 
			
		||||
			if !already {
 | 
			
		||||
				names = append(names, name)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if len(names) == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	unchecked := make([]*User, 0, len(names))
 | 
			
		||||
	if err := e.
 | 
			
		||||
		Where("`user`.is_active = ?", true).
 | 
			
		||||
		And("`user`.prohibit_login = ?", false).
 | 
			
		||||
		In("`user`.lower_name", names).
 | 
			
		||||
		Find(&unchecked); err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("find mentioned users: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	for _, user := range unchecked {
 | 
			
		||||
		if already := resolved[user.LowerName]; already || user.IsOrganization() {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		// Normal users must have read access to the referencing issue
 | 
			
		||||
		perm, err := getUserRepoPermission(e, issue.Repo, user)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("getUserRepoPermission [%d]: %v", user.ID, err)
 | 
			
		||||
		}
 | 
			
		||||
		if !perm.CanReadIssuesOrPulls(issue.IsPull) {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		users = append(users, user)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -387,11 +387,18 @@ func (c *Comment) MailParticipants(opType ActionType, issue *Issue) (err error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *Comment) mailParticipants(e Engine, opType ActionType, issue *Issue) (err error) {
 | 
			
		||||
	mentions := markup.FindAllMentions(c.Content)
 | 
			
		||||
	if err = UpdateIssueMentions(e, c.IssueID, mentions); err != nil {
 | 
			
		||||
	rawMentions := markup.FindAllMentions(c.Content)
 | 
			
		||||
	userMentions, err := issue.ResolveMentionsByVisibility(e, c.Poster, rawMentions)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("ResolveMentionsByVisibility [%d]: %v", c.IssueID, err)
 | 
			
		||||
	}
 | 
			
		||||
	if err = UpdateIssueMentions(e, c.IssueID, userMentions); err != nil {
 | 
			
		||||
		return fmt.Errorf("UpdateIssueMentions [%d]: %v", c.IssueID, err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	mentions := make([]string, len(userMentions))
 | 
			
		||||
	for i, u := range userMentions {
 | 
			
		||||
		mentions[i] = u.LowerName
 | 
			
		||||
	}
 | 
			
		||||
	if len(c.Content) > 0 {
 | 
			
		||||
		if err = mailIssueCommentToParticipants(e, issue, c.Poster, c.Content, c, mentions); err != nil {
 | 
			
		||||
			log.Error("mailIssueCommentToParticipants: %v", err)
 | 
			
		||||
@@ -886,6 +893,7 @@ func CreateCodeComment(doer *User, repo *Repository, issue *Issue, content, tree
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	// FIXME validate treePath
 | 
			
		||||
	// Get latest commit referencing the commented line
 | 
			
		||||
 
 | 
			
		||||
@@ -123,11 +123,18 @@ func (issue *Issue) MailParticipants(doer *User, opType ActionType) (err error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (issue *Issue) mailParticipants(e Engine, doer *User, opType ActionType) (err error) {
 | 
			
		||||
	mentions := markup.FindAllMentions(issue.Content)
 | 
			
		||||
 | 
			
		||||
	if err = UpdateIssueMentions(e, issue.ID, mentions); err != nil {
 | 
			
		||||
	rawMentions := markup.FindAllMentions(issue.Content)
 | 
			
		||||
	userMentions, err := issue.ResolveMentionsByVisibility(e, doer, rawMentions)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("ResolveMentionsByVisibility [%d]: %v", issue.ID, err)
 | 
			
		||||
	}
 | 
			
		||||
	if err = UpdateIssueMentions(e, issue.ID, userMentions); err != nil {
 | 
			
		||||
		return fmt.Errorf("UpdateIssueMentions [%d]: %v", issue.ID, err)
 | 
			
		||||
	}
 | 
			
		||||
	mentions := make([]string, len(userMentions))
 | 
			
		||||
	for i, u := range userMentions {
 | 
			
		||||
		mentions[i] = u.LowerName
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(issue.Content) > 0 {
 | 
			
		||||
		if err = mailIssueCommentToParticipants(e, issue, doer, issue.Content, nil, mentions); err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ package models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"code.gitea.io/gitea/modules/setting"
 | 
			
		||||
@@ -290,6 +291,10 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m.IsClosed = isClosed
 | 
			
		||||
	if isClosed {
 | 
			
		||||
		m.ClosedDateUnix = util.TimeStamp(time.Now().Unix())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = updateMilestone(sess, m); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -311,71 +316,74 @@ func ChangeMilestoneStatus(m *Milestone, isClosed bool) (err error) {
 | 
			
		||||
	return sess.Commit()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func changeMilestoneIssueStats(e *xorm.Session, issue *Issue) error {
 | 
			
		||||
	if issue.MilestoneID == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
func updateMilestoneTotalNum(e Engine, milestoneID int64) (err error) {
 | 
			
		||||
	if _, err = e.Exec("UPDATE `milestone` SET num_issues=(SELECT count(*) FROM issue WHERE milestone_id=?) WHERE id=?",
 | 
			
		||||
		milestoneID,
 | 
			
		||||
		milestoneID,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m, err := getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	_, err = e.Exec("UPDATE `milestone` SET completeness=100*num_closed_issues/(CASE WHEN num_issues > 0 THEN num_issues ELSE 1 END) WHERE id=?",
 | 
			
		||||
		milestoneID,
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func updateMilestoneClosedNum(e Engine, milestoneID int64) (err error) {
 | 
			
		||||
	if _, err = e.Exec("UPDATE `milestone` SET num_closed_issues=(SELECT count(*) FROM issue WHERE milestone_id=? AND is_closed=?) WHERE id=?",
 | 
			
		||||
		milestoneID,
 | 
			
		||||
		true,
 | 
			
		||||
		milestoneID,
 | 
			
		||||
	); err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if issue.IsClosed {
 | 
			
		||||
		m.NumOpenIssues--
 | 
			
		||||
		m.NumClosedIssues++
 | 
			
		||||
	} else {
 | 
			
		||||
		m.NumOpenIssues++
 | 
			
		||||
		m.NumClosedIssues--
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return updateMilestone(e, m)
 | 
			
		||||
	_, err = e.Exec("UPDATE `milestone` SET completeness=100*num_closed_issues/(CASE WHEN num_issues > 0 THEN num_issues ELSE 1 END) WHERE id=?",
 | 
			
		||||
		milestoneID,
 | 
			
		||||
	)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func changeMilestoneAssign(e *xorm.Session, doer *User, issue *Issue, oldMilestoneID int64) error {
 | 
			
		||||
	if err := updateIssueCols(e, issue, "milestone_id"); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if oldMilestoneID > 0 {
 | 
			
		||||
		m, err := getMilestoneByRepoID(e, issue.RepoID, oldMilestoneID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
		if err := updateMilestoneTotalNum(e, oldMilestoneID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m.NumIssues--
 | 
			
		||||
		if issue.IsClosed {
 | 
			
		||||
			m.NumClosedIssues--
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = updateMilestone(e, m); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
			if err := updateMilestoneClosedNum(e, oldMilestoneID); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if issue.MilestoneID > 0 {
 | 
			
		||||
		m, err := getMilestoneByRepoID(e, issue.RepoID, issue.MilestoneID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
		if err := updateMilestoneTotalNum(e, issue.MilestoneID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m.NumIssues++
 | 
			
		||||
		if issue.IsClosed {
 | 
			
		||||
			m.NumClosedIssues++
 | 
			
		||||
			if err := updateMilestoneClosedNum(e, issue.MilestoneID); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if err = updateMilestone(e, m); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err := issue.loadRepo(e); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if oldMilestoneID > 0 || issue.MilestoneID > 0 {
 | 
			
		||||
		if err := issue.loadRepo(e); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if _, err := createMilestoneComment(e, doer, issue.Repo, issue, oldMilestoneID, issue.MilestoneID); err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return updateIssueCols(e, issue, "milestone_id")
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ChangeMilestoneAssign changes assignment of milestone for issue.
 | 
			
		||||
 
 | 
			
		||||
@@ -231,7 +231,7 @@ func TestChangeMilestoneStatus(t *testing.T) {
 | 
			
		||||
	CheckConsistencyFor(t, &Repository{ID: milestone.RepoID}, &Milestone{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestChangeMilestoneIssueStats(t *testing.T) {
 | 
			
		||||
func TestUpdateMilestoneClosedNum(t *testing.T) {
 | 
			
		||||
	assert.NoError(t, PrepareTestDatabase())
 | 
			
		||||
	issue := AssertExistsAndLoadBean(t, &Issue{MilestoneID: 1},
 | 
			
		||||
		"is_closed=0").(*Issue)
 | 
			
		||||
@@ -240,14 +240,14 @@ func TestChangeMilestoneIssueStats(t *testing.T) {
 | 
			
		||||
	issue.ClosedUnix = util.TimeStampNow()
 | 
			
		||||
	_, err := x.Cols("is_closed", "closed_unix").Update(issue)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue))
 | 
			
		||||
	assert.NoError(t, updateMilestoneClosedNum(x, issue.MilestoneID))
 | 
			
		||||
	CheckConsistencyFor(t, &Milestone{})
 | 
			
		||||
 | 
			
		||||
	issue.IsClosed = false
 | 
			
		||||
	issue.ClosedUnix = 0
 | 
			
		||||
	_, err = x.Cols("is_closed", "closed_unix").Update(issue)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.NoError(t, changeMilestoneIssueStats(x.NewSession(), issue))
 | 
			
		||||
	assert.NoError(t, updateMilestoneClosedNum(x, issue.MilestoneID))
 | 
			
		||||
	CheckConsistencyFor(t, &Milestone{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -320,3 +320,35 @@ func TestIssue_SearchIssueIDsByKeyword(t *testing.T) {
 | 
			
		||||
	assert.EqualValues(t, 1, total)
 | 
			
		||||
	assert.EqualValues(t, []int64{1}, ids)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestIssue_ResolveMentions(t *testing.T) {
 | 
			
		||||
	assert.NoError(t, PrepareTestDatabase())
 | 
			
		||||
 | 
			
		||||
	testSuccess := func(owner, repo, doer string, mentions []string, expected []int64) {
 | 
			
		||||
		o := AssertExistsAndLoadBean(t, &User{LowerName: owner}).(*User)
 | 
			
		||||
		r := AssertExistsAndLoadBean(t, &Repository{OwnerID: o.ID, LowerName: repo}).(*Repository)
 | 
			
		||||
		issue := &Issue{RepoID: r.ID}
 | 
			
		||||
		d := AssertExistsAndLoadBean(t, &User{LowerName: doer}).(*User)
 | 
			
		||||
		resolved, err := issue.ResolveMentionsByVisibility(x, d, mentions)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		ids := make([]int64, len(resolved))
 | 
			
		||||
		for i, user := range resolved {
 | 
			
		||||
			ids[i] = user.ID
 | 
			
		||||
		}
 | 
			
		||||
		sort.Slice(ids, func(i, j int) bool { return ids[i] < ids[j] })
 | 
			
		||||
		assert.EqualValues(t, expected, ids)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Public repo, existing user
 | 
			
		||||
	testSuccess("user2", "repo1", "user1", []string{"user5"}, []int64{5})
 | 
			
		||||
	// Public repo, non-existing user
 | 
			
		||||
	testSuccess("user2", "repo1", "user1", []string{"nonexisting"}, []int64{})
 | 
			
		||||
	// Public repo, doer
 | 
			
		||||
	testSuccess("user2", "repo1", "user1", []string{"user1"}, []int64{})
 | 
			
		||||
	// Private repo, team member
 | 
			
		||||
	testSuccess("user17", "big_test_private_4", "user20", []string{"user2"}, []int64{2})
 | 
			
		||||
	// Private repo, not a team member
 | 
			
		||||
	testSuccess("user17", "big_test_private_4", "user20", []string{"user5"}, []int64{})
 | 
			
		||||
	// Private repo, whole team
 | 
			
		||||
	testSuccess("user17", "big_test_private_4", "user15", []string{"owners"}, []int64{18})
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -384,9 +384,11 @@ func dropTableColumns(sess *xorm.Session, tableName string, columnNames ...strin
 | 
			
		||||
		}
 | 
			
		||||
		for _, index := range res {
 | 
			
		||||
			indexName := index["column_name"]
 | 
			
		||||
			_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName))
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			if len(indexName) > 0 {
 | 
			
		||||
				_, err := sess.Exec(fmt.Sprintf("DROP INDEX `%s` ON `%s`", indexName, tableName))
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ func releaseAddColumnIsTagAndSyncTags(x *xorm.Engine) error {
 | 
			
		||||
			if err = models.SyncReleasesWithTags(repo, gitRepo); err != nil {
 | 
			
		||||
				log.Warn("SyncReleasesWithTags: %v", err)
 | 
			
		||||
			}
 | 
			
		||||
			gitRepo.Close()
 | 
			
		||||
		}
 | 
			
		||||
		if len(repos) < pageSize {
 | 
			
		||||
			break
 | 
			
		||||
 
 | 
			
		||||
@@ -91,6 +91,7 @@ func fixReleaseSha1OnReleaseTable(x *xorm.Engine) error {
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				defer gitRepo.Close()
 | 
			
		||||
				gitRepoCache[release.RepoID] = gitRepo
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -252,7 +252,7 @@ func (t *Team) UnitEnabled(tp UnitType) bool {
 | 
			
		||||
 | 
			
		||||
func (t *Team) unitEnabled(e Engine, tp UnitType) bool {
 | 
			
		||||
	if err := t.getUnits(e); err != nil {
 | 
			
		||||
		log.Warn("Error loading repository (ID: %d) units: %s", t.ID, err.Error())
 | 
			
		||||
		log.Warn("Error loading team (ID: %d) units: %s", t.ID, err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, unit := range t.Units {
 | 
			
		||||
 
 | 
			
		||||
@@ -338,15 +338,19 @@ func (pr *PullRequest) GetLastCommitStatus() (status *CommitStatus, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer headGitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	repo := pr.HeadRepo
 | 
			
		||||
	lastCommitID, err := headGitRepo.GetBranchCommitID(pr.HeadBranch)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var statusList []*CommitStatus
 | 
			
		||||
	statusList, err = GetLatestCommitStatus(repo, lastCommitID, 0)
 | 
			
		||||
	err = pr.GetBaseRepo()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	statusList, err := GetLatestCommitStatus(pr.BaseRepo, lastCommitID, 0)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
@@ -524,6 +528,7 @@ func (pr *PullRequest) getMergeCommit() (*git.Commit, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := gitRepo.GetCommit(mergeCommit[:40])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -917,6 +922,7 @@ func (pr *PullRequest) UpdatePatch() (err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer headGitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	// Add a temporary remote.
 | 
			
		||||
	tmpRemote := com.ToStr(time.Now().UnixNano())
 | 
			
		||||
@@ -958,6 +964,7 @@ func (pr *PullRequest) PushToBaseRepo() (err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer headGitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	tmpRemoteName := fmt.Sprintf("tmp-pull-%d", pr.ID)
 | 
			
		||||
	if err = headGitRepo.AddRemote(tmpRemoteName, pr.BaseRepo.RepoPath(), false); err != nil {
 | 
			
		||||
@@ -1147,6 +1154,7 @@ func checkForInvalidation(requests PullRequestList, repoID int64, doer *User, br
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("PullRequestList.InvalidateCodeComments: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		gitRepo.Close()
 | 
			
		||||
	}()
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,7 @@ func (r *Release) LoadAttributes() error {
 | 
			
		||||
 | 
			
		||||
// APIURL the api url for a release. release must have attributes loaded
 | 
			
		||||
func (r *Release) APIURL() string {
 | 
			
		||||
	return fmt.Sprintf("%sapi/v1/%s/releases/%d",
 | 
			
		||||
	return fmt.Sprintf("%sapi/v1/repos/%s/releases/%d",
 | 
			
		||||
		setting.AppURL, r.Repo.FullName(), r.ID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -397,13 +397,15 @@ func UpdateRelease(doer *User, gitRepo *git.Repository, rel *Release, attachment
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err = addReleaseAttachments(rel.ID, attachmentUUIDs); err != nil {
 | 
			
		||||
		log.Error("addReleaseAttachments: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = rel.loadAttributes(x)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err = addReleaseAttachments(rel.ID, attachmentUUIDs)
 | 
			
		||||
 | 
			
		||||
	mode, _ := AccessLevel(doer, rel.Repo)
 | 
			
		||||
	if err1 := PrepareWebhooks(rel.Repo, HookEventRelease, &api.ReleasePayload{
 | 
			
		||||
		Action:     api.HookReleaseUpdated,
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ func TestRelease_Create(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	assert.NoError(t, CreateRelease(gitRepo, &Release{
 | 
			
		||||
		RepoID:       repo.ID,
 | 
			
		||||
@@ -115,6 +116,7 @@ func TestRelease_MirrorDelete(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	findOptions := FindReleasesOptions{IncludeDrafts: true, IncludeTags: true}
 | 
			
		||||
	initCount, err := GetReleaseCountByRepoID(mirror.ID, findOptions)
 | 
			
		||||
 
 | 
			
		||||
@@ -707,11 +707,24 @@ func (repo *Repository) CanEnableEditor() bool {
 | 
			
		||||
	return !repo.IsMirror
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetReaders returns all users that have explicit read access or higher to the repository.
 | 
			
		||||
func (repo *Repository) GetReaders() (_ []*User, err error) {
 | 
			
		||||
	return repo.getUsersWithAccessMode(x, AccessModeRead)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetWriters returns all users that have write access to the repository.
 | 
			
		||||
func (repo *Repository) GetWriters() (_ []*User, err error) {
 | 
			
		||||
	return repo.getUsersWithAccessMode(x, AccessModeWrite)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsReader returns true if user has explicit read access or higher to the repository.
 | 
			
		||||
func (repo *Repository) IsReader(userID int64) (bool, error) {
 | 
			
		||||
	if repo.OwnerID == userID {
 | 
			
		||||
		return true, nil
 | 
			
		||||
	}
 | 
			
		||||
	return x.Where("repo_id = ? AND user_id = ? AND mode >= ?", repo.ID, userID, AccessModeRead).Get(&Access{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// getUsersWithAccessMode returns users that have at least given access mode to the repository.
 | 
			
		||||
func (repo *Repository) getUsersWithAccessMode(e Engine, mode AccessMode) (_ []*User, err error) {
 | 
			
		||||
	if err = repo.getOwner(e); err != nil {
 | 
			
		||||
@@ -937,6 +950,7 @@ func MigrateRepository(doer, u *User, opts MigrateRepoOptions) (*Repository, err
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return repo, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	repo.IsEmpty, err = gitRepo.IsEmpty()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -1050,7 +1064,7 @@ func CleanUpMigrateInfo(repo *Repository) (*Repository, error) {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
 | 
			
		||||
	_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
 | 
			
		||||
	if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
 | 
			
		||||
		return repo, fmt.Errorf("CleanUpMigrateInfo: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
@@ -1473,6 +1487,13 @@ func TransferOwnership(doer *User, newOwnerName string, repo *Repository) error
 | 
			
		||||
		return fmt.Errorf("update owner: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Update pull request headusername
 | 
			
		||||
	if _, err := sess.Where("head_repo_id = ?", repo.ID).Update(&PullRequest{
 | 
			
		||||
		HeadUserName: newOwner.LowerName,
 | 
			
		||||
	}); err != nil {
 | 
			
		||||
		return fmt.Errorf("update pull request: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Remove redundant collaborators.
 | 
			
		||||
	collaborators, err := repo.getCollaborators(sess)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -1882,12 +1903,11 @@ func DeleteRepository(doer *User, uid, repoID int64) error {
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if count > 1 {
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		oidPath := filepath.Join(v.Oid[0:2], v.Oid[2:4], v.Oid[4:len(v.Oid)])
 | 
			
		||||
		oidPath := filepath.Join(setting.LFS.ContentPath, v.Oid[0:2], v.Oid[2:4], v.Oid[4:len(v.Oid)])
 | 
			
		||||
		removeAllWithNotice(sess, "Delete orphaned LFS file", oidPath)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,6 +64,8 @@ func GetActivityStats(repo *Repository, timeFrom time.Time, releases, issues, pr
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
		}
 | 
			
		||||
		defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		code, err := gitRepo.GetCodeActivityStats(timeFrom, repo.DefaultBranch)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, fmt.Errorf("FillFromGit: %v", err)
 | 
			
		||||
@@ -79,6 +81,8 @@ func GetActivityStatsTopAuthors(repo *Repository, timeFrom time.Time, count int)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	code, err := gitRepo.GetCodeActivityStats(timeFrom, "")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("FillFromGit: %v", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -23,6 +23,7 @@ func (repo *Repository) GetBranch(branch string) (*git.Branch, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	return gitRepo.GetBranch(branch)
 | 
			
		||||
}
 | 
			
		||||
@@ -38,6 +39,7 @@ func (repo *Repository) CheckBranchName(name string) error {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	branches, err := repo.GetBranches()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -94,6 +96,7 @@ func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName st
 | 
			
		||||
		log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
 | 
			
		||||
		return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if err = gitRepo.CreateBranch(branchName, oldBranchName); err != nil {
 | 
			
		||||
		log.Error("Unable to create branch: %s from %s. (%v)", branchName, oldBranchName, err)
 | 
			
		||||
@@ -140,6 +143,7 @@ func (repo *Repository) CreateNewBranchFromCommit(doer *User, commit, branchName
 | 
			
		||||
		log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
 | 
			
		||||
		return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if err = gitRepo.CreateBranch(branchName, commit); err != nil {
 | 
			
		||||
		log.Error("Unable to create branch: %s from %s. (%v)", branchName, commit, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -134,7 +134,7 @@ func (m *Mirror) FullAddress() string {
 | 
			
		||||
func (m *Mirror) SaveAddress(addr string) error {
 | 
			
		||||
	repoPath := m.Repo.RepoPath()
 | 
			
		||||
	// Remove old origin
 | 
			
		||||
	_, err := git.NewCommand("remote", "remove", "origin").RunInDir(repoPath)
 | 
			
		||||
	_, err := git.NewCommand("remote", "rm", "origin").RunInDir(repoPath)
 | 
			
		||||
	if err != nil && !strings.HasPrefix(err.Error(), "exit status 128 - fatal: No such remote ") {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -242,6 +242,7 @@ func (m *Mirror) runSync() ([]*mirrorSyncResult, bool) {
 | 
			
		||||
	if err = SyncReleasesWithTags(m.Repo, gitRepo); err != nil {
 | 
			
		||||
		log.Error("Failed to synchronize tags to releases for repository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if err := m.Repo.UpdateSize(); err != nil {
 | 
			
		||||
		log.Error("Failed to update size for mirror repository: %v", err)
 | 
			
		||||
@@ -426,6 +427,8 @@ func SyncMirrors() {
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
		// Get latest commit date and update to current repository updated time
 | 
			
		||||
		commitDate, err := git.GetLatestCommitTime(m.Repo.RepoPath())
 | 
			
		||||
		if err != nil {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +0,0 @@
 | 
			
		||||
// Copyright 2019 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 models
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"code.gitea.io/gitea/modules/git"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// GetTagsByPath returns repo tags by its path
 | 
			
		||||
func GetTagsByPath(path string) ([]*git.Tag, error) {
 | 
			
		||||
	gitRepo, err := git.OpenRepository(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return gitRepo.GetTagInfos()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTags return repo's tags
 | 
			
		||||
func (repo *Repository) GetTags() ([]*git.Tag, error) {
 | 
			
		||||
	return GetTagsByPath(repo.RepoPath())
 | 
			
		||||
}
 | 
			
		||||
@@ -32,7 +32,7 @@ import (
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tplCommentPrefix = `# gitea public key`
 | 
			
		||||
	tplPublicKey     = tplCommentPrefix + "\n" + `command="%s serv key-%d --config='%s'",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
 | 
			
		||||
	tplPublicKey     = tplCommentPrefix + "\n" + `command="%s --config='%s' serv key-%d",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty %s` + "\n"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var sshOpLocker sync.Mutex
 | 
			
		||||
@@ -77,7 +77,7 @@ func (key *PublicKey) OmitEmail() string {
 | 
			
		||||
 | 
			
		||||
// AuthorizedString returns formatted public key string for authorized_keys file.
 | 
			
		||||
func (key *PublicKey) AuthorizedString() string {
 | 
			
		||||
	return fmt.Sprintf(tplPublicKey, setting.AppPath, key.ID, setting.CustomConf, key.Content)
 | 
			
		||||
	return fmt.Sprintf(tplPublicKey, setting.AppPath, setting.CustomConf, key.ID, key.Content)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func extractTypeFromBase64Key(key string) (string, error) {
 | 
			
		||||
@@ -315,6 +315,18 @@ func appendAuthorizedKeysToFile(keys ...*PublicKey) error {
 | 
			
		||||
	sshOpLocker.Lock()
 | 
			
		||||
	defer sshOpLocker.Unlock()
 | 
			
		||||
 | 
			
		||||
	if setting.SSH.RootPath != "" {
 | 
			
		||||
		// First of ensure that the RootPath is present, and if not make it with 0700 permissions
 | 
			
		||||
		// This of course doesn't guarantee that this is the right directory for authorized_keys
 | 
			
		||||
		// but at least if it's supposed to be this directory and it doesn't exist and we're the
 | 
			
		||||
		// right user it will at least be created properly.
 | 
			
		||||
		err := os.MkdirAll(setting.SSH.RootPath, 0700)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
 | 
			
		||||
	f, err := os.OpenFile(fPath, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -602,6 +614,18 @@ func rewriteAllPublicKeys(e Engine) error {
 | 
			
		||||
	sshOpLocker.Lock()
 | 
			
		||||
	defer sshOpLocker.Unlock()
 | 
			
		||||
 | 
			
		||||
	if setting.SSH.RootPath != "" {
 | 
			
		||||
		// First of ensure that the RootPath is present, and if not make it with 0700 permissions
 | 
			
		||||
		// This of course doesn't guarantee that this is the right directory for authorized_keys
 | 
			
		||||
		// but at least if it's supposed to be this directory and it doesn't exist and we're the
 | 
			
		||||
		// right user it will at least be created properly.
 | 
			
		||||
		err := os.MkdirAll(setting.SSH.RootPath, 0700)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Error("Unable to MkdirAll(%s): %v", setting.SSH.RootPath, err)
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fPath := filepath.Join(setting.SSH.RootPath, "authorized_keys")
 | 
			
		||||
	tmpPath := fPath + ".tmp"
 | 
			
		||||
	t, err := os.OpenFile(tmpPath, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600)
 | 
			
		||||
 
 | 
			
		||||
@@ -211,6 +211,7 @@ func pushUpdate(opts PushUpdateOptions) (repo *Repository, err error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, fmt.Errorf("OpenRepository: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if err = repo.UpdateSize(); err != nil {
 | 
			
		||||
		log.Error("Failed to update size for repository: %v", err)
 | 
			
		||||
 
 | 
			
		||||
@@ -1645,7 +1645,12 @@ func SyncExternalUsers() {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			sr := s.LDAP().SearchEntries()
 | 
			
		||||
			sr, err := s.LDAP().SearchEntries()
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				log.Error("SyncExternalUsers LDAP source failure [%s], skipped", s.Name)
 | 
			
		||||
				continue
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for _, su := range sr {
 | 
			
		||||
				if len(su.Username) == 0 {
 | 
			
		||||
					continue
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
 | 
			
		||||
		CountResult int
 | 
			
		||||
		JSONResult  string
 | 
			
		||||
	}{
 | 
			
		||||
		{2, 1, `[{"timestamp":1540080000,"contributions":1}]`},
 | 
			
		||||
		{2, 1, `[{"timestamp":1571616000,"contributions":1}]`},
 | 
			
		||||
		{3, 0, `[]`},
 | 
			
		||||
	}
 | 
			
		||||
	// Prepare
 | 
			
		||||
@@ -41,7 +41,7 @@ func TestGetUserHeatmapDataByUser(t *testing.T) {
 | 
			
		||||
		// Get the heatmap and compare
 | 
			
		||||
		heatmap, err := GetUserHeatmapDataByUser(user)
 | 
			
		||||
		assert.NoError(t, err)
 | 
			
		||||
		assert.Equal(t, len(actions), len(heatmap))
 | 
			
		||||
		assert.Equal(t, len(actions), len(heatmap), "invalid action count: did the test data became too old?")
 | 
			
		||||
		assert.Equal(t, tc.CountResult, len(heatmap))
 | 
			
		||||
 | 
			
		||||
		//Test JSON rendering
 | 
			
		||||
 
 | 
			
		||||
@@ -236,6 +236,7 @@ func getMSTeamsPushPayload(p *api.PushPayload) (*MSTeamsPayload, error) {
 | 
			
		||||
				ActivityTitle:    p.Sender.FullName,
 | 
			
		||||
				ActivitySubtitle: p.Sender.UserName,
 | 
			
		||||
				ActivityImage:    p.Sender.AvatarURL,
 | 
			
		||||
				Text:             text,
 | 
			
		||||
				Facts: []MSTeamsFact{
 | 
			
		||||
					{
 | 
			
		||||
						Name:  "Repository:",
 | 
			
		||||
 
 | 
			
		||||
@@ -140,6 +140,7 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
 | 
			
		||||
		log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
 | 
			
		||||
		return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if hasMasterBranch {
 | 
			
		||||
		if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
 | 
			
		||||
@@ -276,6 +277,7 @@ func (repo *Repository) DeleteWikiPage(doer *User, wikiName string) (err error)
 | 
			
		||||
		log.Error("Unable to open temporary repository: %s (%v)", basePath, err)
 | 
			
		||||
		return fmt.Errorf("Failed to open new temporary repository in: %s %v", basePath, err)
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	if err := gitRepo.ReadTreeToIndex("HEAD"); err != nil {
 | 
			
		||||
		log.Error("Unable to read HEAD tree to index in: %s %v", basePath, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -161,6 +161,7 @@ func TestRepository_AddWikiPage(t *testing.T) {
 | 
			
		||||
			// Now need to show that the page has been added:
 | 
			
		||||
			gitRepo, err := git.OpenRepository(repo.WikiPath())
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			defer gitRepo.Close()
 | 
			
		||||
			masterTree, err := gitRepo.GetTree("master")
 | 
			
		||||
			assert.NoError(t, err)
 | 
			
		||||
			wikiPath := WikiNameToFilename(wikiName)
 | 
			
		||||
@@ -214,6 +215,7 @@ func TestRepository_EditWikiPage(t *testing.T) {
 | 
			
		||||
			_, err := masterTree.GetTreeEntryByPath("Home.md")
 | 
			
		||||
			assert.Error(t, err)
 | 
			
		||||
		}
 | 
			
		||||
		gitRepo.Close()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -226,6 +228,7 @@ func TestRepository_DeleteWikiPage(t *testing.T) {
 | 
			
		||||
	// Now need to show that the page has been added:
 | 
			
		||||
	gitRepo, err := git.OpenRepository(repo.WikiPath())
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
	masterTree, err := gitRepo.GetTree("master")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	wikiPath := WikiNameToFilename("Home")
 | 
			
		||||
 
 | 
			
		||||
@@ -308,12 +308,12 @@ func (ls *Source) UsePagedSearch() bool {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SearchEntries : search an LDAP source for all users matching userFilter
 | 
			
		||||
func (ls *Source) SearchEntries() []*SearchResult {
 | 
			
		||||
func (ls *Source) SearchEntries() ([]*SearchResult, error) {
 | 
			
		||||
	l, err := dial(ls)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("LDAP Connect error, %s:%v", ls.Host, err)
 | 
			
		||||
		ls.Enabled = false
 | 
			
		||||
		return nil
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer l.Close()
 | 
			
		||||
 | 
			
		||||
@@ -321,7 +321,7 @@ func (ls *Source) SearchEntries() []*SearchResult {
 | 
			
		||||
		err := l.Bind(ls.BindDN, ls.BindPassword)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			log.Debug("Failed to bind as BindDN[%s]: %v", ls.BindDN, err)
 | 
			
		||||
			return nil
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		log.Trace("Bound as BindDN %s", ls.BindDN)
 | 
			
		||||
	} else {
 | 
			
		||||
@@ -350,7 +350,7 @@ func (ls *Source) SearchEntries() []*SearchResult {
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		log.Error("LDAP Search failed unexpectedly! (%v)", err)
 | 
			
		||||
		return nil
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	result := make([]*SearchResult, len(sr.Entries))
 | 
			
		||||
@@ -368,5 +368,5 @@ func (ls *Source) SearchEntries() []*SearchResult {
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return result
 | 
			
		||||
	return result, nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -187,7 +187,16 @@ func ReferencesGitRepo(allowEmpty bool) macaron.Handler {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			ctx.Repo.GitRepo = gitRepo
 | 
			
		||||
			// We opened it, we should close it
 | 
			
		||||
			defer func() {
 | 
			
		||||
				// If it's been set to nil then assume someone else has closed it.
 | 
			
		||||
				if ctx.Repo.GitRepo != nil {
 | 
			
		||||
					ctx.Repo.GitRepo.Close()
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ctx.Next()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -249,6 +249,19 @@ func Contexter() macaron.Handler {
 | 
			
		||||
		if ctx.Query("go-get") == "1" {
 | 
			
		||||
			ownerName := c.Params(":username")
 | 
			
		||||
			repoName := c.Params(":reponame")
 | 
			
		||||
			trimmedRepoName := strings.TrimSuffix(repoName, ".git")
 | 
			
		||||
 | 
			
		||||
			if ownerName == "" || trimmedRepoName == "" {
 | 
			
		||||
				_, _ = c.Write([]byte(`<!doctype html>
 | 
			
		||||
<html>
 | 
			
		||||
	<body>
 | 
			
		||||
		invalid import path
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
`))
 | 
			
		||||
				c.WriteHeader(400)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			branchName := "master"
 | 
			
		||||
 | 
			
		||||
			repo, err := models.GetRepositoryByOwnerAndName(ownerName, repoName)
 | 
			
		||||
@@ -276,7 +289,7 @@ func Contexter() macaron.Handler {
 | 
			
		||||
	</body>
 | 
			
		||||
</html>
 | 
			
		||||
`, map[string]string{
 | 
			
		||||
				"GoGetImport":    ComposeGoGetImport(ownerName, strings.TrimSuffix(repoName, ".git")),
 | 
			
		||||
				"GoGetImport":    ComposeGoGetImport(ownerName, trimmedRepoName),
 | 
			
		||||
				"CloneLink":      models.ComposeHTTPSCloneURL(ownerName, repoName),
 | 
			
		||||
				"GoDocDirectory": prefix + "{/dir}",
 | 
			
		||||
				"GoDocFile":      prefix + "{/dir}/{file}#L{line}",
 | 
			
		||||
 
 | 
			
		||||
@@ -62,7 +62,7 @@ func HandleOrgAssignment(ctx *Context, args ...bool) {
 | 
			
		||||
 | 
			
		||||
	// Force redirection when username is actually a user.
 | 
			
		||||
	if !org.IsOrganization() {
 | 
			
		||||
		ctx.Redirect("/" + org.Name)
 | 
			
		||||
		ctx.Redirect(setting.AppSubURL + "/" + org.Name)
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -201,10 +201,14 @@ func ComposeGoGetImport(owner, repo string) string {
 | 
			
		||||
// .netrc file.
 | 
			
		||||
func EarlyResponseForGoGetMeta(ctx *Context) {
 | 
			
		||||
	username := ctx.Params(":username")
 | 
			
		||||
	reponame := ctx.Params(":reponame")
 | 
			
		||||
	reponame := strings.TrimSuffix(ctx.Params(":reponame"), ".git")
 | 
			
		||||
	if username == "" || reponame == "" {
 | 
			
		||||
		ctx.PlainText(400, []byte("invalid repository path"))
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	ctx.PlainText(200, []byte(com.Expand(`<meta name="go-import" content="{GoGetImport} git {CloneLink}">`,
 | 
			
		||||
		map[string]string{
 | 
			
		||||
			"GoGetImport": ComposeGoGetImport(username, strings.TrimSuffix(reponame, ".git")),
 | 
			
		||||
			"GoGetImport": ComposeGoGetImport(username, reponame),
 | 
			
		||||
			"CloneLink":   models.ComposeHTTPSCloneURL(username, reponame),
 | 
			
		||||
		})))
 | 
			
		||||
}
 | 
			
		||||
@@ -229,7 +233,7 @@ func RedirectToRepo(ctx *Context, redirectRepoID int64) {
 | 
			
		||||
	if ctx.Req.URL.RawQuery != "" {
 | 
			
		||||
		redirectPath += "?" + ctx.Req.URL.RawQuery
 | 
			
		||||
	}
 | 
			
		||||
	ctx.Redirect(redirectPath)
 | 
			
		||||
	ctx.Redirect(path.Join(setting.AppSubURL, redirectPath))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func repoAssignment(ctx *Context, repo *models.Repository) {
 | 
			
		||||
@@ -360,6 +364,13 @@ func RepoAssignment() macaron.Handler {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Repo.GitRepo = gitRepo
 | 
			
		||||
		// We opened it, we should close it
 | 
			
		||||
		defer func() {
 | 
			
		||||
			// If it's been set to nil then assume someone else has closed it.
 | 
			
		||||
			if ctx.Repo.GitRepo != nil {
 | 
			
		||||
				ctx.Repo.GitRepo.Close()
 | 
			
		||||
			}
 | 
			
		||||
		}()
 | 
			
		||||
		ctx.Repo.RepoLink = repo.Link()
 | 
			
		||||
		ctx.Data["RepoLink"] = ctx.Repo.RepoLink
 | 
			
		||||
		ctx.Data["RepoRelPath"] = ctx.Repo.Owner.Name + "/" + ctx.Repo.Repository.Name
 | 
			
		||||
@@ -422,6 +433,7 @@ func RepoAssignment() macaron.Handler {
 | 
			
		||||
		// repo is empty and display enable
 | 
			
		||||
		if ctx.Repo.Repository.IsEmpty {
 | 
			
		||||
			ctx.Data["BranchName"] = ctx.Repo.Repository.DefaultBranch
 | 
			
		||||
			ctx.Next()
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -472,6 +484,7 @@ func RepoAssignment() macaron.Handler {
 | 
			
		||||
			ctx.Data["GoDocDirectory"] = prefix + "{/dir}"
 | 
			
		||||
			ctx.Data["GoDocFile"] = prefix + "{/dir}/{file}#L{line}"
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Next()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -577,6 +590,13 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
 | 
			
		||||
				ctx.ServerError("RepoRef Invalid repo "+repoPath, err)
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			// We opened it, we should close it
 | 
			
		||||
			defer func() {
 | 
			
		||||
				// If it's been set to nil then assume someone else has closed it.
 | 
			
		||||
				if ctx.Repo.GitRepo != nil {
 | 
			
		||||
					ctx.Repo.GitRepo.Close()
 | 
			
		||||
				}
 | 
			
		||||
			}()
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Get default branch.
 | 
			
		||||
@@ -665,6 +685,8 @@ func RepoRefByType(refType RepoRefType) macaron.Handler {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount
 | 
			
		||||
 | 
			
		||||
		ctx.Next()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -87,10 +87,11 @@ func (r *BlameReader) Close() error {
 | 
			
		||||
 | 
			
		||||
// CreateBlameReader creates reader for given repository, commit and file
 | 
			
		||||
func CreateBlameReader(repoPath, commitID, file string) (*BlameReader, error) {
 | 
			
		||||
	_, err := OpenRepository(repoPath)
 | 
			
		||||
	gitRepo, err := OpenRepository(repoPath)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	return createBlameReader(repoPath, GitExecutable, "blame", commitID, "--porcelain", "--", file)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,8 @@ THE SOFTWARE.
 | 
			
		||||
`
 | 
			
		||||
	repo, err := OpenRepository("../../.git")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
 | 
			
		||||
	testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 | 
			
		||||
@@ -55,6 +57,8 @@ func Benchmark_Blob_Data(b *testing.B) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
 | 
			
		||||
	testBlob, err := repo.GetBlob("a8d4b49dd073a4a38a7e58385eeff7cc52568697")
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatal(err)
 | 
			
		||||
 
 | 
			
		||||
@@ -77,6 +77,8 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	testGetCommitsInfo(t, bareRepo1)
 | 
			
		||||
 | 
			
		||||
	clonedPath, err := cloneRepo(bareRepo1Path, testReposDir, "repo1_TestEntries_GetCommitsInfo")
 | 
			
		||||
@@ -84,6 +86,8 @@ func TestEntries_GetCommitsInfo(t *testing.T) {
 | 
			
		||||
	defer os.RemoveAll(clonedPath)
 | 
			
		||||
	clonedRepo1, err := OpenRepository(clonedPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer clonedRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	testGetCommitsInfo(t, clonedRepo1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -101,13 +105,16 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
 | 
			
		||||
	for _, benchmark := range benchmarks {
 | 
			
		||||
		var commit *Commit
 | 
			
		||||
		var entries Entries
 | 
			
		||||
		var repo *Repository
 | 
			
		||||
		if repoPath, err := cloneRepo(benchmark.url, benchmarkReposDir, benchmark.name); err != nil {
 | 
			
		||||
			b.Fatal(err)
 | 
			
		||||
		} else if repo, err := OpenRepository(repoPath); err != nil {
 | 
			
		||||
		} else if repo, err = OpenRepository(repoPath); err != nil {
 | 
			
		||||
			b.Fatal(err)
 | 
			
		||||
		} else if commit, err = repo.GetBranchCommit("master"); err != nil {
 | 
			
		||||
			repo.Close()
 | 
			
		||||
			b.Fatal(err)
 | 
			
		||||
		} else if entries, err = commit.Tree.ListEntries(); err != nil {
 | 
			
		||||
			repo.Close()
 | 
			
		||||
			b.Fatal(err)
 | 
			
		||||
		}
 | 
			
		||||
		entries.Sort()
 | 
			
		||||
@@ -120,5 +127,6 @@ func BenchmarkEntries_GetCommitsInfo(b *testing.B) {
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		})
 | 
			
		||||
		repo.Close()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -90,6 +90,11 @@ func (h *Hook) Update() error {
 | 
			
		||||
		h.IsActive = false
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	d := filepath.Dir(h.path)
 | 
			
		||||
	if err := os.MkdirAll(d, os.ModePerm); err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
 
 | 
			
		||||
@@ -7,7 +7,7 @@ package git
 | 
			
		||||
import (
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
 | 
			
		||||
	"gopkg.in/src-d/go-git.v4/plumbing"
 | 
			
		||||
	"gopkg.in/src-d/go-git.v4/plumbing/object"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// NotesRef is the git ref where Gitea will look for git-notes data.
 | 
			
		||||
@@ -27,13 +27,28 @@ func GetNote(repo *Repository, commitID string, note *Note) error {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	entry, err := notes.GetTreeEntryByPath(commitID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	remainingCommitID := commitID
 | 
			
		||||
	path := ""
 | 
			
		||||
	currentTree := notes.Tree.gogitTree
 | 
			
		||||
	var file *object.File
 | 
			
		||||
	for len(remainingCommitID) > 2 {
 | 
			
		||||
		file, err = currentTree.File(remainingCommitID)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			path += remainingCommitID
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		if err == object.ErrFileNotFound {
 | 
			
		||||
			currentTree, err = currentTree.Tree(remainingCommitID[0:2])
 | 
			
		||||
			path += remainingCommitID[0:2] + "/"
 | 
			
		||||
			remainingCommitID = remainingCommitID[2:]
 | 
			
		||||
		}
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	blob := entry.Blob()
 | 
			
		||||
	dataRc, err := blob.DataAsync()
 | 
			
		||||
	blob := file.Blob
 | 
			
		||||
	dataRc, err := blob.Reader()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
@@ -45,26 +60,21 @@ func GetNote(repo *Repository, commitID string, note *Note) error {
 | 
			
		||||
	}
 | 
			
		||||
	note.Message = d
 | 
			
		||||
 | 
			
		||||
	commit, err := repo.gogitRepo.CommitObject(plumbing.Hash(notes.ID))
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commitNodeIndex, commitGraphFile := repo.CommitNodeIndex()
 | 
			
		||||
	if commitGraphFile != nil {
 | 
			
		||||
		defer commitGraphFile.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commitNode, err := commitNodeIndex.Get(commit.Hash)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	lastCommits, err := getLastCommitForPaths(commitNode, "", []string{commitID})
 | 
			
		||||
	commitNode, err := commitNodeIndex.Get(notes.ID)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	note.Commit = convertCommit(lastCommits[commitID])
 | 
			
		||||
 | 
			
		||||
	lastCommits, err := getLastCommitForPaths(commitNode, "", []string{path})
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	note.Commit = convertCommit(lastCommits[path])
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ func TestGetNotes(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	note := Note{}
 | 
			
		||||
	err = GetNote(bareRepo1, "95bb4d39648ee7e325106df01a621c530863a653", ¬e)
 | 
			
		||||
@@ -22,3 +23,18 @@ func TestGetNotes(t *testing.T) {
 | 
			
		||||
	assert.Equal(t, []byte("Note contents\n"), note.Message)
 | 
			
		||||
	assert.Equal(t, "Vladimir Panteleev", note.Commit.Author.Name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestGetNestedNotes(t *testing.T) {
 | 
			
		||||
	repoPath := filepath.Join(testReposDir, "repo3_notes")
 | 
			
		||||
	repo, err := OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
 | 
			
		||||
	note := Note{}
 | 
			
		||||
	err = GetNote(repo, "3e668dbfac39cbc80a9ff9c61eb565d944453ba4", ¬e)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, []byte("Note 2"), note.Message)
 | 
			
		||||
	err = GetNote(repo, "ba0a96fa63532d6c5087ecef070b0250ed72fa47", ¬e)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.Equal(t, []byte("Note 1"), note.Message)
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ import (
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	gitealog "code.gitea.io/gitea/modules/log"
 | 
			
		||||
	"github.com/Unknwon/com"
 | 
			
		||||
	"gopkg.in/src-d/go-billy.v4/osfs"
 | 
			
		||||
	gogit "gopkg.in/src-d/go-git.v4"
 | 
			
		||||
@@ -107,6 +108,21 @@ func OpenRepository(repoPath string) (*Repository, error) {
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close this repository, in particular close the underlying gogitStorage if this is not nil
 | 
			
		||||
func (repo *Repository) Close() {
 | 
			
		||||
	if repo == nil || repo.gogitStorage == nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	if err := repo.gogitStorage.Close(); err != nil {
 | 
			
		||||
		gitealog.Error("Error closing storage: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GoGitRepo gets the go-git repo representation
 | 
			
		||||
func (repo *Repository) GoGitRepo() *gogit.Repository {
 | 
			
		||||
	return repo.gogitRepo
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsEmpty Check if repository is empty.
 | 
			
		||||
func (repo *Repository) IsEmpty() (bool, error) {
 | 
			
		||||
	var errbuf strings.Builder
 | 
			
		||||
 
 | 
			
		||||
@@ -17,6 +17,7 @@ func TestRepository_GetBlob_Found(t *testing.T) {
 | 
			
		||||
	repoPath := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	r, err := OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
		OID  string
 | 
			
		||||
@@ -44,6 +45,7 @@ func TestRepository_GetBlob_NotExist(t *testing.T) {
 | 
			
		||||
	repoPath := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	r, err := OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	testCase := "0000000000000000000000000000000000000000"
 | 
			
		||||
	testError := ErrNotExist{testCase, ""}
 | 
			
		||||
@@ -57,6 +59,7 @@ func TestRepository_GetBlob_NoId(t *testing.T) {
 | 
			
		||||
	repoPath := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	r, err := OpenRepository(repoPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	testCase := ""
 | 
			
		||||
	testError := fmt.Errorf("Length must be 40: %s", testCase)
 | 
			
		||||
 
 | 
			
		||||
@@ -28,8 +28,14 @@ func IsBranchExist(repoPath, name string) bool {
 | 
			
		||||
 | 
			
		||||
// IsBranchExist returns true if given branch exists in current repository.
 | 
			
		||||
func (repo *Repository) IsBranchExist(name string) bool {
 | 
			
		||||
	_, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true)
 | 
			
		||||
	return err == nil
 | 
			
		||||
	if name == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	reference, err := repo.gogitRepo.Reference(plumbing.ReferenceName(BranchPrefix+name), true)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return reference.Type() != plumbing.InvalidReference
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Branch represents a Git branch.
 | 
			
		||||
@@ -102,6 +108,7 @@ func GetBranchesByPath(path string) ([]*Branch, error) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer gitRepo.Close()
 | 
			
		||||
 | 
			
		||||
	brs, err := gitRepo.GetBranches()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
@@ -165,7 +172,7 @@ func (repo *Repository) AddRemote(name, url string, fetch bool) error {
 | 
			
		||||
 | 
			
		||||
// RemoveRemote removes a remote from repository.
 | 
			
		||||
func (repo *Repository) RemoveRemote(name string) error {
 | 
			
		||||
	_, err := NewCommand("remote", "remove", name).RunInDir(repo.Path)
 | 
			
		||||
	_, err := NewCommand("remote", "rm", name).RunInDir(repo.Path)
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ func TestRepository_GetBranches(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	branches, err := bareRepo1.GetBranches()
 | 
			
		||||
 | 
			
		||||
@@ -29,6 +30,7 @@ func BenchmarkRepository_GetBranches(b *testing.B) {
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		b.Fatal(err)
 | 
			
		||||
	}
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < b.N; i++ {
 | 
			
		||||
		_, err := bareRepo1.GetBranches()
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ func TestRepository_GetCommitBranches(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	// these test case are specific to the repo1_bare test repo
 | 
			
		||||
	testCases := []struct {
 | 
			
		||||
@@ -40,6 +41,9 @@ func TestRepository_GetCommitBranches(t *testing.T) {
 | 
			
		||||
func TestGetTagCommitWithSignature(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := bareRepo1.GetCommit("3ad28a9149a2864384548f3d17ed7f38014c9e8a")
 | 
			
		||||
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
@@ -52,6 +56,9 @@ func TestGetTagCommitWithSignature(t *testing.T) {
 | 
			
		||||
func TestGetCommitWithBadCommitID(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := bareRepo1.GetCommit("bad_branch")
 | 
			
		||||
	assert.Nil(t, commit)
 | 
			
		||||
	assert.Error(t, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ func TestGetFormatPatch(t *testing.T) {
 | 
			
		||||
	defer os.RemoveAll(clonedPath)
 | 
			
		||||
	repo, err := OpenRepository(clonedPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
	rd, err := repo.GetFormatPatch("8d92fc95^", "8d92fc95")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	patchb, err := ioutil.ReadAll(rd)
 | 
			
		||||
 
 | 
			
		||||
@@ -15,6 +15,7 @@ func TestRepository_GetRefs(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	refs, err := bareRepo1.GetRefs()
 | 
			
		||||
 | 
			
		||||
@@ -38,6 +39,7 @@ func TestRepository_GetRefsFiltered(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	refs, err := bareRepo1.GetRefsFiltered(TagPrefix)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	timeFrom, err := time.Parse(time.RFC3339, "2016-01-01T00:00:00+00:00")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -153,15 +153,18 @@ func (repo *Repository) GetTagNameBySHA(sha string) (string, error) {
 | 
			
		||||
 | 
			
		||||
// GetTagID returns the object ID for a tag (annotated tags have both an object SHA AND a commit SHA)
 | 
			
		||||
func (repo *Repository) GetTagID(name string) (string, error) {
 | 
			
		||||
	stdout, err := NewCommand("show-ref", "--", name).RunInDir(repo.Path)
 | 
			
		||||
	stdout, err := NewCommand("show-ref", "--tags", "--", name).RunInDir(repo.Path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	fields := strings.Fields(stdout)
 | 
			
		||||
	if len(fields) != 2 {
 | 
			
		||||
		return "", ErrNotExist{ID: name}
 | 
			
		||||
	// Make sure exact match is used: "v1" != "release/v1"
 | 
			
		||||
	for _, line := range strings.Split(stdout, "\n") {
 | 
			
		||||
		fields := strings.Fields(line)
 | 
			
		||||
		if len(fields) == 2 && fields[1] == "refs/tags/"+name {
 | 
			
		||||
			return fields[0], nil
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return fields[0], nil
 | 
			
		||||
	return "", ErrNotExist{ID: name}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetTag returns a Git tag by given name.
 | 
			
		||||
 
 | 
			
		||||
@@ -16,6 +16,7 @@ func TestRepository_GetTags(t *testing.T) {
 | 
			
		||||
	bareRepo1Path := filepath.Join(testReposDir, "repo1_bare")
 | 
			
		||||
	bareRepo1, err := OpenRepository(bareRepo1Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	tags, err := bareRepo1.GetTagInfos()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
@@ -34,6 +35,7 @@ func TestRepository_GetTag(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	bareRepo1, err := OpenRepository(clonedPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
 | 
			
		||||
	lTagName := "lightweightTag"
 | 
			
		||||
@@ -62,6 +64,16 @@ func TestRepository_GetTag(t *testing.T) {
 | 
			
		||||
	assert.NotEqual(t, aTagID, aTag.Object.String())
 | 
			
		||||
	assert.EqualValues(t, aTagCommitID, aTag.Object.String())
 | 
			
		||||
	assert.EqualValues(t, "tag", aTag.Type)
 | 
			
		||||
 | 
			
		||||
	rTagCommitID := "8006ff9adbf0cb94da7dad9e537e53817f9fa5c0"
 | 
			
		||||
	rTagName := "release/" + lTagName
 | 
			
		||||
	bareRepo1.CreateTag(rTagName, rTagCommitID)
 | 
			
		||||
	rTagID, err := bareRepo1.GetTagID(rTagName)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.EqualValues(t, rTagCommitID, rTagID)
 | 
			
		||||
	oTagID, err := bareRepo1.GetTagID(lTagName)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.EqualValues(t, lTagCommitID, oTagID)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func TestRepository_GetAnnotatedTag(t *testing.T) {
 | 
			
		||||
@@ -73,6 +85,7 @@ func TestRepository_GetAnnotatedTag(t *testing.T) {
 | 
			
		||||
 | 
			
		||||
	bareRepo1, err := OpenRepository(clonedPath)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer bareRepo1.Close()
 | 
			
		||||
 | 
			
		||||
	lTagCommitID := "6fbd69e9823458e6c4a2fc5c0f6bc022b2f2acd1"
 | 
			
		||||
	lTagName := "lightweightTag"
 | 
			
		||||
 
 | 
			
		||||
@@ -30,6 +30,7 @@ func TestRepoIsEmpty(t *testing.T) {
 | 
			
		||||
	emptyRepo2Path := filepath.Join(testReposDir, "repo2_empty")
 | 
			
		||||
	repo, err := OpenRepository(emptyRepo2Path)
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer repo.Close()
 | 
			
		||||
	isEmpty, err := repo.IsEmpty()
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	assert.True(t, isEmpty)
 | 
			
		||||
 
 | 
			
		||||
@@ -6,11 +6,13 @@
 | 
			
		||||
package git
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"os"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/mcuadros/go-version"
 | 
			
		||||
	"gopkg.in/src-d/go-git.v4/plumbing"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
@@ -63,6 +65,11 @@ type CommitTreeOpts struct {
 | 
			
		||||
 | 
			
		||||
// CommitTree creates a commit from a given tree id for the user with provided message
 | 
			
		||||
func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOpts) (SHA1, error) {
 | 
			
		||||
	binVersion, err := BinVersion()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return SHA1{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	commitTimeStr := time.Now().Format(time.RFC3339)
 | 
			
		||||
 | 
			
		||||
	// Because this may call hooks we should pass in the environment
 | 
			
		||||
@@ -80,20 +87,24 @@ func (repo *Repository) CommitTree(sig *Signature, tree *Tree, opts CommitTreeOp
 | 
			
		||||
		cmd.AddArguments("-p", parent)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cmd.AddArguments("-m", opts.Message)
 | 
			
		||||
	messageBytes := new(bytes.Buffer)
 | 
			
		||||
	_, _ = messageBytes.WriteString(opts.Message)
 | 
			
		||||
	_, _ = messageBytes.WriteString("\n")
 | 
			
		||||
 | 
			
		||||
	if opts.KeyID != "" {
 | 
			
		||||
		cmd.AddArguments(fmt.Sprintf("-S%s", opts.KeyID))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if opts.NoGPGSign {
 | 
			
		||||
	if version.Compare(binVersion, "2.0.0", ">=") && opts.NoGPGSign {
 | 
			
		||||
		cmd.AddArguments("--no-gpg-sign")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	res, err := cmd.RunInDirWithEnv(repo.Path, env)
 | 
			
		||||
	stdout := new(bytes.Buffer)
 | 
			
		||||
	stderr := new(bytes.Buffer)
 | 
			
		||||
	err = cmd.RunInDirTimeoutEnvFullPipeline(env, -1, repo.Path, stdout, stderr, messageBytes)
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return SHA1{}, err
 | 
			
		||||
		return SHA1{}, concatenateError(err, stderr.String())
 | 
			
		||||
	}
 | 
			
		||||
	return NewIDFromString(strings.TrimSpace(res))
 | 
			
		||||
	return NewIDFromString(strings.TrimSpace(stdout.String()))
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo3_notes/COMMIT_EDITMSG
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo3_notes/COMMIT_EDITMSG
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
2
 | 
			
		||||
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo3_notes/HEAD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo3_notes/HEAD
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
ref: refs/heads/master
 | 
			
		||||
							
								
								
									
										7
									
								
								modules/git/tests/repos/repo3_notes/config
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								modules/git/tests/repos/repo3_notes/config
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
[core]
 | 
			
		||||
	repositoryformatversion = 0
 | 
			
		||||
	filemode = false
 | 
			
		||||
	bare = false
 | 
			
		||||
	logallrefupdates = true
 | 
			
		||||
	symlinks = false
 | 
			
		||||
	ignorecase = true
 | 
			
		||||
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo3_notes/description
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo3_notes/description
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
Unnamed repository; edit this file 'description' to name the repository.
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								modules/git/tests/repos/repo3_notes/index
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								modules/git/tests/repos/repo3_notes/index
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										2
									
								
								modules/git/tests/repos/repo3_notes/logs/HEAD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								modules/git/tests/repos/repo3_notes/logs/HEAD
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
0000000000000000000000000000000000000000 ba0a96fa63532d6c5087ecef070b0250ed72fa47 Filip Navara <filip.navara@gmail.com> 1567767895 +0200	commit (initial): 1
 | 
			
		||||
ba0a96fa63532d6c5087ecef070b0250ed72fa47 3e668dbfac39cbc80a9ff9c61eb565d944453ba4 Filip Navara <filip.navara@gmail.com> 1567767909 +0200	commit: 2
 | 
			
		||||
@@ -0,0 +1,2 @@
 | 
			
		||||
0000000000000000000000000000000000000000 ba0a96fa63532d6c5087ecef070b0250ed72fa47 Filip Navara <filip.navara@gmail.com> 1567767895 +0200	commit (initial): 1
 | 
			
		||||
ba0a96fa63532d6c5087ecef070b0250ed72fa47 3e668dbfac39cbc80a9ff9c61eb565d944453ba4 Filip Navara <filip.navara@gmail.com> 1567767909 +0200	commit: 2
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
x<01><>;<0E>0@<40>s
 | 
			
		||||
<EFBFBD>H<EFBFBD><EFBFBD>&v*!<21><><EFBFBD><1D>4<EFBFBD>J<EFBFBD><4A>(p~
 | 
			
		||||
G`|oxzi<7A><69><EFBFBD><01>;<3B><>3<EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>6<EFBFBD><0B>$`<60>"NR<4E>ѺXla<6C>i<EFBFBD>K<EFBFBD><4B><EFBFBD><17><><EFBFBD>4r<34>$<24>\P0"ỵPQ'F_<46><5F>V<EFBFBD>N<EFBFBD>i<EFBFBD><69><EFBFBD><EFBFBD>*<2A>ʗ<EFBFBD><CA97>G<EFBFBD><47><EFBFBD>ӳK<D3B3>|<06>Y<EFBFBD>e<EFBFBD><01>H<EFBFBD>f<EFBFBD><66>f<EFBFBD><0C><0F><>Em
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
x<01><>;<0E>0<05>}<7D><><EFBFBD>"ǿu$<24>RQr<51><72><EFBFBD>K1F<31><46><EFBFBD>1<1C>nf<6E><66>R-%w<><77>zc<06><>{<7B>%7<><37>h#<23>x<EFBFBD><78><EFBFBD>Q<EFBFBD><51><EFBFBD>fXѻ?j<>K<EFBFBD><4B><0B><>S#8<>צ<EFBFBD><D7A6><EFBFBD>{<7B><>M<EFBFBD><4D>3<EFBFBD>> <20><><EFBFBD><EFBFBD><EFBFBD>6Z<36>Q<EFBFBD>m<EFBFBD><6D><07><0E>8<EFBFBD>
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo3_notes/refs/heads/master
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo3_notes/refs/heads/master
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
3e668dbfac39cbc80a9ff9c61eb565d944453ba4
 | 
			
		||||
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo3_notes/refs/notes/commits
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo3_notes/refs/notes/commits
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
654c8b6b63c08bf37f638d3f521626b7fbbd4d37
 | 
			
		||||
@@ -56,6 +56,7 @@ func TestEntriesCustomSort(t *testing.T) {
 | 
			
		||||
func TestFollowLink(t *testing.T) {
 | 
			
		||||
	r, err := OpenRepository("tests/repos/repo1_bare")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
	defer r.Close()
 | 
			
		||||
 | 
			
		||||
	commit, err := r.GetCommit("37991dec2c8e592043f47155ce4808d4580f9123")
 | 
			
		||||
	assert.NoError(t, err)
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@ func Middleware(options ...Options) macaron.Handler {
 | 
			
		||||
		// OK we should proxy the response writer
 | 
			
		||||
		// We are still not necessarily going to compress...
 | 
			
		||||
		proxyWriter := &ProxyResponseWriter{
 | 
			
		||||
			ResponseWriter: ctx.Resp,
 | 
			
		||||
			internal: ctx.Resp,
 | 
			
		||||
		}
 | 
			
		||||
		defer proxyWriter.Close()
 | 
			
		||||
 | 
			
		||||
@@ -137,19 +137,52 @@ func Middleware(options ...Options) macaron.Handler {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		ctx.Next()
 | 
			
		||||
		ctx.Resp = proxyWriter.internal
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ProxyResponseWriter is a wrapped macaron ResponseWriter that may compress its contents
 | 
			
		||||
type ProxyResponseWriter struct {
 | 
			
		||||
	writer io.WriteCloser
 | 
			
		||||
	macaron.ResponseWriter
 | 
			
		||||
	stopped bool
 | 
			
		||||
	writer   io.WriteCloser
 | 
			
		||||
	internal macaron.ResponseWriter
 | 
			
		||||
	stopped  bool
 | 
			
		||||
 | 
			
		||||
	code int
 | 
			
		||||
	buf  []byte
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Header returns the header map
 | 
			
		||||
func (proxy *ProxyResponseWriter) Header() http.Header {
 | 
			
		||||
	return proxy.internal.Header()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Status returns the status code of the response or 0 if the response has not been written.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Status() int {
 | 
			
		||||
	if proxy.code != 0 {
 | 
			
		||||
		return proxy.code
 | 
			
		||||
	}
 | 
			
		||||
	return proxy.internal.Status()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Written returns whether or not the ResponseWriter has been written.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Written() bool {
 | 
			
		||||
	if proxy.code != 0 {
 | 
			
		||||
		return true
 | 
			
		||||
	}
 | 
			
		||||
	return proxy.internal.Written()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Size returns the size of the response body.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Size() int {
 | 
			
		||||
	return proxy.internal.Size()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Before allows for a function to be called before the ResponseWriter has been written to. This is
 | 
			
		||||
// useful for setting headers or any other operations that must happen before a response has been written.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Before(before macaron.BeforeFunc) {
 | 
			
		||||
	proxy.internal.Before(before)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write appends data to the proxied gzip writer.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Write(b []byte) (int, error) {
 | 
			
		||||
	// if writer is initialized, use the writer
 | 
			
		||||
@@ -210,7 +243,7 @@ func (proxy *ProxyResponseWriter) startGzip() error {
 | 
			
		||||
 | 
			
		||||
	// Write the header to gzip response.
 | 
			
		||||
	if proxy.code != 0 {
 | 
			
		||||
		proxy.ResponseWriter.WriteHeader(proxy.code)
 | 
			
		||||
		proxy.internal.WriteHeader(proxy.code)
 | 
			
		||||
		// Ensure that no other WriteHeader's happen
 | 
			
		||||
		proxy.code = 0
 | 
			
		||||
	}
 | 
			
		||||
@@ -220,7 +253,7 @@ func (proxy *ProxyResponseWriter) startGzip() error {
 | 
			
		||||
	// write the gzip header even if nothing was ever written.
 | 
			
		||||
	if len(proxy.buf) > 0 {
 | 
			
		||||
		// Initialize the GZIP response.
 | 
			
		||||
		proxy.writer = writerPool.Get(proxy.ResponseWriter)
 | 
			
		||||
		proxy.writer = writerPool.Get(proxy.internal)
 | 
			
		||||
 | 
			
		||||
		return proxy.writeBuf()
 | 
			
		||||
	}
 | 
			
		||||
@@ -229,11 +262,11 @@ func (proxy *ProxyResponseWriter) startGzip() error {
 | 
			
		||||
 | 
			
		||||
func (proxy *ProxyResponseWriter) startPlain() error {
 | 
			
		||||
	if proxy.code != 0 {
 | 
			
		||||
		proxy.ResponseWriter.WriteHeader(proxy.code)
 | 
			
		||||
		proxy.internal.WriteHeader(proxy.code)
 | 
			
		||||
		proxy.code = 0
 | 
			
		||||
	}
 | 
			
		||||
	proxy.stopped = true
 | 
			
		||||
	proxy.writer = noopCloser{proxy.ResponseWriter}
 | 
			
		||||
	proxy.writer = noopCloser{proxy.internal}
 | 
			
		||||
	return proxy.writeBuf()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -295,13 +328,13 @@ func (proxy *ProxyResponseWriter) Flush() {
 | 
			
		||||
		gw.Flush()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	proxy.ResponseWriter.Flush()
 | 
			
		||||
	proxy.internal.Flush()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hijack implements http.Hijacker. If the underlying ResponseWriter is a
 | 
			
		||||
// Hijacker, its Hijack method is returned. Otherwise an error is returned.
 | 
			
		||||
func (proxy *ProxyResponseWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) {
 | 
			
		||||
	hijacker, ok := proxy.ResponseWriter.(http.Hijacker)
 | 
			
		||||
	hijacker, ok := proxy.internal.(http.Hijacker)
 | 
			
		||||
	if !ok {
 | 
			
		||||
		return nil, nil, fmt.Errorf("the ResponseWriter doesn't support the Hijacker interface")
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -155,7 +155,9 @@ func PostLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var req api.LFSLockRequest
 | 
			
		||||
	dec := json.NewDecoder(ctx.Req.Body().ReadCloser())
 | 
			
		||||
	bodyReader := ctx.Req.Body().ReadCloser()
 | 
			
		||||
	defer bodyReader.Close()
 | 
			
		||||
	dec := json.NewDecoder(bodyReader)
 | 
			
		||||
	if err := dec.Decode(&req); err != nil {
 | 
			
		||||
		writeStatus(ctx, 400)
 | 
			
		||||
		return
 | 
			
		||||
@@ -269,7 +271,9 @@ func UnLockHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var req api.LFSLockDeleteRequest
 | 
			
		||||
	dec := json.NewDecoder(ctx.Req.Body().ReadCloser())
 | 
			
		||||
	bodyReader := ctx.Req.Body().ReadCloser()
 | 
			
		||||
	defer bodyReader.Close()
 | 
			
		||||
	dec := json.NewDecoder(bodyReader)
 | 
			
		||||
	if err := dec.Decode(&req); err != nil {
 | 
			
		||||
		writeStatus(ctx, 400)
 | 
			
		||||
		return
 | 
			
		||||
 
 | 
			
		||||
@@ -327,7 +327,9 @@ func PutHandler(ctx *context.Context) {
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	contentStore := &ContentStore{BasePath: setting.LFS.ContentPath}
 | 
			
		||||
	if err := contentStore.Put(meta, ctx.Req.Body().ReadCloser()); err != nil {
 | 
			
		||||
	bodyReader := ctx.Req.Body().ReadCloser()
 | 
			
		||||
	defer bodyReader.Close()
 | 
			
		||||
	if err := contentStore.Put(meta, bodyReader); err != nil {
 | 
			
		||||
		ctx.Resp.WriteHeader(500)
 | 
			
		||||
		fmt.Fprintf(ctx.Resp, `{"message":"%s"}`, err)
 | 
			
		||||
		if err = repository.RemoveLFSMetaObjectByOid(rv.Oid); err != nil {
 | 
			
		||||
@@ -434,7 +436,9 @@ func unpack(ctx *context.Context) *RequestVars {
 | 
			
		||||
 | 
			
		||||
	if r.Method == "POST" { // Maybe also check if +json
 | 
			
		||||
		var p RequestVars
 | 
			
		||||
		dec := json.NewDecoder(r.Body().ReadCloser())
 | 
			
		||||
		bodyReader := r.Body().ReadCloser()
 | 
			
		||||
		defer bodyReader.Close()
 | 
			
		||||
		dec := json.NewDecoder(bodyReader)
 | 
			
		||||
		err := dec.Decode(&p)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return rv
 | 
			
		||||
@@ -453,7 +457,9 @@ func unpackbatch(ctx *context.Context) *BatchVars {
 | 
			
		||||
	r := ctx.Req
 | 
			
		||||
	var bv BatchVars
 | 
			
		||||
 | 
			
		||||
	dec := json.NewDecoder(r.Body().ReadCloser())
 | 
			
		||||
	bodyReader := r.Body().ReadCloser()
 | 
			
		||||
	defer bodyReader.Close()
 | 
			
		||||
	dec := json.NewDecoder(bodyReader)
 | 
			
		||||
	err := dec.Decode(&bv)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return &bv
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user