mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Compare commits
	
		
			40 Commits
		
	
	
		
			v1.21.0-de
			...
			v1.9.0
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					8f29011723 | ||
| 
						 | 
					ee43d20d3b | ||
| 
						 | 
					99ffd826e5 | ||
| 
						 | 
					93bac4e10d | ||
| 
						 | 
					9fbb898058 | ||
| 
						 | 
					0a9794a6bc | ||
| 
						 | 
					d4044b9c98 | ||
| 
						 | 
					1e6d2e47e9 | ||
| 
						 | 
					d827b0bfb7 | ||
| 
						 | 
					d789170e31 | ||
| 
						 | 
					9bbe3eb0b4 | ||
| 
						 | 
					650fdceb5a | ||
| 
						 | 
					4c69e158e5 | ||
| 
						 | 
					b7e41f7b8f | ||
| 
						 | 
					5a3d9861ba | ||
| 
						 | 
					adb43358bc | ||
| 
						 | 
					d6a980501b | ||
| 
						 | 
					103a66ae83 | ||
| 
						 | 
					426fd2a816 | ||
| 
						 | 
					337f2625ac | ||
| 
						 | 
					5ebf4990a5 | ||
| 
						 | 
					3fd07a0be6 | ||
| 
						 | 
					d372539f79 | ||
| 
						 | 
					91e24a3a10 | ||
| 
						 | 
					a29e667eff | ||
| 
						 | 
					92b993c91f | ||
| 
						 | 
					33b1027c76 | ||
| 
						 | 
					b45f9260bf | ||
| 
						 | 
					ee1a8d7b41 | ||
| 
						 | 
					ba19a35b6b | ||
| 
						 | 
					cc8e7dd355 | ||
| 
						 | 
					f52840623c | ||
| 
						 | 
					97d4a38e01 | ||
| 
						 | 
					60ccd87d6e | ||
| 
						 | 
					2477737fff | ||
| 
						 | 
					a360daeff9 | ||
| 
						 | 
					82d4d725ae | ||
| 
						 | 
					1e585d7991 | ||
| 
						 | 
					f849766998 | ||
| 
						 | 
					f4818671e4 | 
							
								
								
									
										67
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										67
									
								
								.drone.yml
									
									
									
									
									
								
							@@ -114,6 +114,17 @@ steps:
 | 
				
			|||||||
        - push
 | 
					        - push
 | 
				
			||||||
        - pull_request
 | 
					        - pull_request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  - name: tag-pre-condition
 | 
				
			||||||
 | 
					    pull: always
 | 
				
			||||||
 | 
					    image: alpine/git
 | 
				
			||||||
 | 
					    commands:
 | 
				
			||||||
 | 
					      - git update-ref refs/heads/tag_test ${DRONE_COMMIT_SHA}
 | 
				
			||||||
 | 
					    depends_on:
 | 
				
			||||||
 | 
					      - build
 | 
				
			||||||
 | 
					    when:
 | 
				
			||||||
 | 
					      event:
 | 
				
			||||||
 | 
					        - tag
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name: tag-test
 | 
					  - name: tag-test
 | 
				
			||||||
    pull: always
 | 
					    pull: always
 | 
				
			||||||
    image: golang:1.12
 | 
					    image: golang:1.12
 | 
				
			||||||
@@ -122,7 +133,7 @@ steps:
 | 
				
			|||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
      TAGS: bindata
 | 
					      TAGS: bindata
 | 
				
			||||||
    depends_on:
 | 
					    depends_on:
 | 
				
			||||||
      - build
 | 
					      - tag-pre-condition
 | 
				
			||||||
    when:
 | 
					    when:
 | 
				
			||||||
      event:
 | 
					      event:
 | 
				
			||||||
        - tag
 | 
					        - tag
 | 
				
			||||||
@@ -442,7 +453,6 @@ trigger:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
depends_on:
 | 
					depends_on:
 | 
				
			||||||
  - testing
 | 
					  - testing
 | 
				
			||||||
  - translations
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
steps:
 | 
					steps:
 | 
				
			||||||
  - name: fetch-tags
 | 
					  - name: fetch-tags
 | 
				
			||||||
@@ -558,6 +568,15 @@ workspace:
 | 
				
			|||||||
  base: /go
 | 
					  base: /go
 | 
				
			||||||
  path: src/code.gitea.io/gitea
 | 
					  path: src/code.gitea.io/gitea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					depends_on:
 | 
				
			||||||
 | 
					  - testing
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					trigger:
 | 
				
			||||||
 | 
					  ref:
 | 
				
			||||||
 | 
					  - refs/heads/master
 | 
				
			||||||
 | 
					  - "refs/tags/**"
 | 
				
			||||||
 | 
					  - "refs/pull/**"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
steps:
 | 
					steps:
 | 
				
			||||||
  - name: fetch-tags
 | 
					  - name: fetch-tags
 | 
				
			||||||
    pull: default
 | 
					    pull: default
 | 
				
			||||||
@@ -571,56 +590,28 @@ steps:
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  - name: dryrun
 | 
					  - name: dryrun
 | 
				
			||||||
    pull: always
 | 
					    pull: always
 | 
				
			||||||
    image: plugins/docker:18.09
 | 
					    image: plugins/docker:linux-amd64
 | 
				
			||||||
    settings:
 | 
					    settings:
 | 
				
			||||||
      cache_from: gitea/gitea
 | 
					 | 
				
			||||||
      dry_run: true
 | 
					      dry_run: true
 | 
				
			||||||
      repo: gitea/gitea
 | 
					      repo: gitea/gitea
 | 
				
			||||||
    when:
 | 
					    when:
 | 
				
			||||||
      event:
 | 
					      event:
 | 
				
			||||||
        - pull_request
 | 
					        - pull_request
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  - name: release
 | 
					  - name: publish
 | 
				
			||||||
    pull: always
 | 
					    pull: always
 | 
				
			||||||
    image: plugins/docker:18.09
 | 
					    image: plugins/docker:linux-amd64
 | 
				
			||||||
    settings:
 | 
					    settings:
 | 
				
			||||||
      cache_from: gitea/gitea
 | 
					      auto_tag: true
 | 
				
			||||||
      repo: gitea/gitea
 | 
					      repo: gitea/gitea
 | 
				
			||||||
      tags:
 | 
					      password:
 | 
				
			||||||
        - "${DRONE_BRANCH##release/v}"
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      DOCKER_PASSWORD:
 | 
					 | 
				
			||||||
        from_secret: docker_password
 | 
					        from_secret: docker_password
 | 
				
			||||||
      DOCKER_USERNAME:
 | 
					      username:
 | 
				
			||||||
        from_secret: docker_username
 | 
					        from_secret: docker_username
 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - dryrun
 | 
					 | 
				
			||||||
    when:
 | 
					    when:
 | 
				
			||||||
      branch:
 | 
					 | 
				
			||||||
        - "release/*"
 | 
					 | 
				
			||||||
      event:
 | 
					      event:
 | 
				
			||||||
        - push
 | 
					        exclude:
 | 
				
			||||||
 | 
					        - pull_request
 | 
				
			||||||
  - name: latest
 | 
					 | 
				
			||||||
    pull: always
 | 
					 | 
				
			||||||
    image: plugins/docker:18.09
 | 
					 | 
				
			||||||
    settings:
 | 
					 | 
				
			||||||
      cache_from: gitea/gitea
 | 
					 | 
				
			||||||
      default_tags: true
 | 
					 | 
				
			||||||
      repo: gitea/gitea
 | 
					 | 
				
			||||||
    environment:
 | 
					 | 
				
			||||||
      DOCKER_PASSWORD:
 | 
					 | 
				
			||||||
        from_secret: docker_password
 | 
					 | 
				
			||||||
      DOCKER_USERNAME:
 | 
					 | 
				
			||||||
        from_secret: docker_username
 | 
					 | 
				
			||||||
    depends_on:
 | 
					 | 
				
			||||||
      - dryrun
 | 
					 | 
				
			||||||
    when:
 | 
					 | 
				
			||||||
      branch:
 | 
					 | 
				
			||||||
        - master
 | 
					 | 
				
			||||||
      event:
 | 
					 | 
				
			||||||
        - push
 | 
					 | 
				
			||||||
        - tag
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
---
 | 
					---
 | 
				
			||||||
kind: pipeline
 | 
					kind: pipeline
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										44
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										44
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -4,9 +4,15 @@ 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
 | 
					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).
 | 
					been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [1.9.0-RC1](https://github.com/go-gitea/gitea/releases/tag/v1.9.0-rc1) - 2019-07-06
 | 
					## [1.9.0](https://github.com/go-gitea/gitea/releases/tag/v1.9.0) - 2019-07-30
 | 
				
			||||||
* BREAKING
 | 
					* BREAKING
 | 
				
			||||||
  * Better logging (#6038) (#6095)
 | 
					  * Better logging (#6038) (#6095)
 | 
				
			||||||
 | 
					* SECURITY
 | 
				
			||||||
 | 
					  * Shadow the password on cache and session config on admin panel (#7300)
 | 
				
			||||||
 | 
					  * Fix markdown invoke sequence (#7513) (#7560)
 | 
				
			||||||
 | 
					  * Reserve .well-known username (#7638)
 | 
				
			||||||
 | 
					  * Do not leak secrets via timing side channel (#7364)
 | 
				
			||||||
 | 
					  * Ensure that decryption of cookie actually suceeds (#7363)
 | 
				
			||||||
* FEATURE
 | 
					* FEATURE
 | 
				
			||||||
  * Content API for Creating, Updating, Deleting Files (#6314)
 | 
					  * Content API for Creating, Updating, Deleting Files (#6314)
 | 
				
			||||||
  * Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
 | 
					  * Enable tls-alpn-01: Use certmanager provided TLSConfig for LetsEncrypt (#7229)
 | 
				
			||||||
@@ -29,6 +35,39 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			|||||||
  * Implement Default Webhooks (#4299)
 | 
					  * Implement Default Webhooks (#4299)
 | 
				
			||||||
  * Telegram webhook (#4227)
 | 
					  * Telegram webhook (#4227)
 | 
				
			||||||
* BUGFIXES
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Send webhook after commit when creating issue with assignees (#7681) (#7684)
 | 
				
			||||||
 | 
					  * Upgrade macaron/captcha to fix random error problem (#7407) (#7683)
 | 
				
			||||||
 | 
					  * Move add to hook queue for created repo to outside xorm session. (#7682) (#7675)
 | 
				
			||||||
 | 
					  * Show protection symbol if needed on default branch (#7660) (#7668)
 | 
				
			||||||
 | 
					  * Hide delete/restore button on archived repos (#7660)
 | 
				
			||||||
 | 
					  * Fix bug on migrating milestone from github (#7665) (#7666) 
 | 
				
			||||||
 | 
					  * Use flex to fix floating paginate (#7656) (#7662)
 | 
				
			||||||
 | 
					  * Change length of some repository's columns (#7652) (#7655)
 | 
				
			||||||
 | 
					  * Fix wrong email when use gitea as OAuth2 provider (#7640) (#7647)
 | 
				
			||||||
 | 
					  * Fix syntax highlight initialization (#7617) (#7626) 
 | 
				
			||||||
 | 
					  * Fix bug create/edit wiki pages when code master branch protected (#7580) (#7623)
 | 
				
			||||||
 | 
					  * Fix panic on push at #7611 (#7615) (#7618)
 | 
				
			||||||
 | 
					  * Handle ErrUserProhibitLogin in http git (#7586, #7591) (#7590) 
 | 
				
			||||||
 | 
					  * Fix color of split-diff view in dark theme (#7587) (#7589)
 | 
				
			||||||
 | 
					  * Fix file header overflow in file and blame views (#7562) (#7579) 
 | 
				
			||||||
 | 
					  * Malformed URLs in API git/commits response (#7565) (#7567)
 | 
				
			||||||
 | 
					  * Fix empty commits now showing in repo overview (#7521) (#7563)
 | 
				
			||||||
 | 
					  * Fix repository's pull request count error (#7518) (#7524) 
 | 
				
			||||||
 | 
					  * Remove duplicated webhook trigger (#7511) (#7516) 
 | 
				
			||||||
 | 
					  * Handles all redirects for Web UI File CRUD (#7478) (#7507)
 | 
				
			||||||
 | 
					  * Fix regex for issues in commit messages (#7444) (#7466)
 | 
				
			||||||
 | 
					  * cmd/serv: actually exit after fatal errors (#7458) (#7460)
 | 
				
			||||||
 | 
					  * Fix an issue with some pages throwing 'not defined' js exceptions #7450 (#7453)
 | 
				
			||||||
 | 
					  * Fix Dropzone.js integration (#7445) (#7448)
 | 
				
			||||||
 | 
					  * Create class for inline positioned lists (#7439) (#7393)
 | 
				
			||||||
 | 
					  * Diff: Fix indentation on unhighlighted code (#7435) (#7443)
 | 
				
			||||||
 | 
					  * jQuery 3 (#7442) (#7425)
 | 
				
			||||||
 | 
					  * Only show "New Pull Request" button if repo allows pulls (#7426) (#7432)
 | 
				
			||||||
 | 
					  * Fix vendor references (#7394) (#7396)
 | 
				
			||||||
 | 
					  * Only return head: null if source branch was deleted (#6705) (#7376)
 | 
				
			||||||
 | 
					  * Add missing template variable on organisation settings (#7386) (#7385)
 | 
				
			||||||
 | 
					  * Fix post parameter on issue list which had unset assignee (#7380) (#7383)
 | 
				
			||||||
 | 
					  * Fix migration tests due to issue 7 being resolved (#7375) (#7381)
 | 
				
			||||||
  * Correctly adjust mirror url (#6593)
 | 
					  * Correctly adjust mirror url (#6593)
 | 
				
			||||||
  * Handle early git version's lack of get-url (#7065)
 | 
					  * Handle early git version's lack of get-url (#7065)
 | 
				
			||||||
  * Fix icon position in issue view (#7354)
 | 
					  * Fix icon position in issue view (#7354)
 | 
				
			||||||
@@ -166,6 +205,7 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			|||||||
  * Disable benchmarking during tag events on DroneIO (#6365)
 | 
					  * Disable benchmarking during tag events on DroneIO (#6365)
 | 
				
			||||||
  * Comments list performance optimization (#5305)
 | 
					  * Comments list performance optimization (#5305)
 | 
				
			||||||
* ENHANCEMENT
 | 
					* ENHANCEMENT
 | 
				
			||||||
 | 
					  * Update Drone docker generation to standard format (#7480) (#7496) (#7504)
 | 
				
			||||||
  * Add API Endpoint for Repo Edit (#7006)
 | 
					  * Add API Endpoint for Repo Edit (#7006)
 | 
				
			||||||
  * Add state param to milestone listing API (#7131)
 | 
					  * Add state param to milestone listing API (#7131)
 | 
				
			||||||
  * Make captcha and password optional for external accounts (#6606)
 | 
					  * Make captcha and password optional for external accounts (#6606)
 | 
				
			||||||
@@ -285,8 +325,6 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			|||||||
  * Refactor: append, build variable and type switch (#4940)
 | 
					  * Refactor: append, build variable and type switch (#4940)
 | 
				
			||||||
  * Git statistics in Activity tab (#4724)
 | 
					  * Git statistics in Activity tab (#4724)
 | 
				
			||||||
  * Drop the bits argument when generating an ed25519 key (#6504)
 | 
					  * Drop the bits argument when generating an ed25519 key (#6504)
 | 
				
			||||||
* SECURITY
 | 
					 | 
				
			||||||
  * Shadow the password on cache and session config on admin panel (#7300)
 | 
					 | 
				
			||||||
* TESTING
 | 
					* TESTING
 | 
				
			||||||
  * Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
 | 
					  * Exclude pull_request from fetch-tags step, fixes #7108 (#7120)
 | 
				
			||||||
  * Refactor and improve git test (#7086)
 | 
					  * Refactor and improve git test (#7086)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -73,7 +73,6 @@ func fail(userMessage, logMessage string, args ...interface{}) {
 | 
				
			|||||||
		if !setting.ProdMode {
 | 
							if !setting.ProdMode {
 | 
				
			||||||
			fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
 | 
								fmt.Fprintf(os.Stderr, logMessage+"\n", args...)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	os.Exit(1)
 | 
						os.Exit(1)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								go.mod
									
									
									
									
									
								
							@@ -45,7 +45,7 @@ require (
 | 
				
			|||||||
	github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e // 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/binding v0.0.0-20160711225916-9440f336b443
 | 
				
			||||||
	github.com/go-macaron/cache v0.0.0-20151013081102-561735312776
 | 
						github.com/go-macaron/cache v0.0.0-20151013081102-561735312776
 | 
				
			||||||
	github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab
 | 
						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-20190309005821-6fd6a9bfe14e9
 | 
				
			||||||
	github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372
 | 
						github.com/go-macaron/csrf v0.0.0-20180426211211-503617c6b372
 | 
				
			||||||
	github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
 | 
						github.com/go-macaron/i18n v0.0.0-20160612092837-ef57533c3b0f
 | 
				
			||||||
@@ -135,4 +135,4 @@ require (
 | 
				
			|||||||
	xorm.io/core v0.6.3
 | 
						xorm.io/core v0.6.3
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
replace github.com/denisenkom/go-mssqldb => github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44
 | 
					replace github.com/denisenkom/go-mssqldb => github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								go.sum
									
									
									
									
									
								
							@@ -66,8 +66,8 @@ github.com/cznic/strutil v0.0.0-20181122101858-275e90344537/go.mod h1:AHHPPPXTw0
 | 
				
			|||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
					github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 | 
				
			||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
					github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 | 
				
			||||||
github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44 h1:x0uHqLQTSEL9LKic8sWDt3ASkq07ve5ojIIUl5uF64M=
 | 
					github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44 h1:DWxZh2sImfCFn/79OUBhzFkPTKnsdDzXH/JTxpw5n6w=
 | 
				
			||||||
github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
 | 
					github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44/go.mod h1:xN/JuLBIz4bjkxNmByTiV1IbhfnYb6oo99phBn4Eqhc=
 | 
				
			||||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
 | 
					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/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/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
 | 
				
			||||||
@@ -113,8 +113,8 @@ github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443 h1:i801KPR7j76u
 | 
				
			|||||||
github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM=
 | 
					github.com/go-macaron/binding v0.0.0-20160711225916-9440f336b443/go.mod h1:u+H6rwW+HQwUL+w5uaEJSpIlVZDye1o9MB4Su0JfRfM=
 | 
				
			||||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw=
 | 
					github.com/go-macaron/cache v0.0.0-20151013081102-561735312776 h1:UYIHS1r0WotqB5cIa0PAiV0m6GzD9rDBcn4alp5JgCw=
 | 
				
			||||||
github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok=
 | 
					github.com/go-macaron/cache v0.0.0-20151013081102-561735312776/go.mod h1:hHAsZm/oBZVcY+S7qdQL6Vbg5VrXF6RuKGuqsszt3Ok=
 | 
				
			||||||
github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab h1:4VFhsA3GE5Wwq1Ymr8KWCmrOWi1wRLEgdj48LPfQjxI=
 | 
					github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df h1:MdgvtI3Y1u/DHNj7xUGOqAv+KGoTikjy8xQtCm12L78=
 | 
				
			||||||
github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab/go.mod h1:j9TJ+0nwUOWBvNnm0bheHIPFf3cC62EQo7n7O6PbjZA=
 | 
					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 h1:A0QGzY6UHHEil0I2e7C21JenNNG0mmrj5d9SFWTlgr8=
 | 
				
			||||||
github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/go.mod h1:utmMRnVIrXPSfA9MFcpIYKEpKawjKxf62vv62k4707E=
 | 
					github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9/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 h1:acrx8CnDmlKl+BPoOOLEK9Ko+SrWFB5pxRuGkKj4iqo=
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,6 +65,7 @@ var (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const issueRefRegexpStr = `(?:([0-9a-zA-Z-_\.]+)/([0-9a-zA-Z-_\.]+))?(#[0-9]+)+`
 | 
					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|$))`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func assembleKeywordsPattern(words []string) string {
 | 
					func assembleKeywordsPattern(words []string) string {
 | 
				
			||||||
	return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
 | 
						return fmt.Sprintf(`(?i)(?:%s)(?::?) %s`, strings.Join(words, "|"), issueRefRegexpStr)
 | 
				
			||||||
@@ -73,7 +74,7 @@ func assembleKeywordsPattern(words []string) string {
 | 
				
			|||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	issueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueCloseKeywords))
 | 
						issueCloseKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueCloseKeywords))
 | 
				
			||||||
	issueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueReopenKeywords))
 | 
						issueReopenKeywordsPat = regexp.MustCompile(assembleKeywordsPattern(issueReopenKeywords))
 | 
				
			||||||
	issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStr)
 | 
						issueReferenceKeywordsPat = regexp.MustCompile(issueRefRegexpStrNoKeyword)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Action represents user operation type and other information to
 | 
					// Action represents user operation type and other information to
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -155,6 +155,25 @@ func TestPushCommits_AvatarLink(t *testing.T) {
 | 
				
			|||||||
		pushCommits.AvatarLink("nonexistent@example.com"))
 | 
							pushCommits.AvatarLink("nonexistent@example.com"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestRegExp_issueReferenceKeywordsPat(t *testing.T) {
 | 
				
			||||||
 | 
						trueTestCases := []string{
 | 
				
			||||||
 | 
							"#2",
 | 
				
			||||||
 | 
							"[#2]",
 | 
				
			||||||
 | 
							"please see go-gitea/gitea#5",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						falseTestCases := []string{
 | 
				
			||||||
 | 
							"kb#2",
 | 
				
			||||||
 | 
							"#2xy",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, testCase := range trueTestCases {
 | 
				
			||||||
 | 
							assert.True(t, issueReferenceKeywordsPat.MatchString(testCase))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, testCase := range falseTestCases {
 | 
				
			||||||
 | 
							assert.False(t, issueReferenceKeywordsPat.MatchString(testCase))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Test_getIssueFromRef(t *testing.T) {
 | 
					func Test_getIssueFromRef(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
	repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
						repo := AssertExistsAndLoadBean(t, &Repository{ID: 1}).(*Repository)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -101,7 +101,7 @@ func (protectBranch *ProtectedBranch) HasEnoughApprovals(pr *PullRequest) bool {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist.
 | 
					// GetGrantedApprovalsCount returns the number of granted approvals for pr. A granted approval must be authored by a user in an approval whitelist.
 | 
				
			||||||
func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 {
 | 
					func (protectBranch *ProtectedBranch) GetGrantedApprovalsCount(pr *PullRequest) int64 {
 | 
				
			||||||
	reviews, err := GetReviewersByPullID(pr.Issue.ID)
 | 
						reviews, err := GetReviewersByPullID(pr.IssueID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error("GetReviewersByPullID: %v", err)
 | 
							log.Error("GetReviewersByPullID: %v", err)
 | 
				
			||||||
		return 0
 | 
							return 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,13 +12,13 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// PushingEnvironment returns an os environment to allow hooks to work on push
 | 
					// PushingEnvironment returns an os environment to allow hooks to work on push
 | 
				
			||||||
func PushingEnvironment(doer *User, repo *Repository) []string {
 | 
					func PushingEnvironment(doer *User, repo *Repository) []string {
 | 
				
			||||||
	return FullPushingEnvironment(doer, doer, repo, 0)
 | 
						return FullPushingEnvironment(doer, doer, repo, repo.Name, 0)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// FullPushingEnvironment returns an os environment to allow hooks to work on push
 | 
					// FullPushingEnvironment returns an os environment to allow hooks to work on push
 | 
				
			||||||
func FullPushingEnvironment(author, committer *User, repo *Repository, prID int64) []string {
 | 
					func FullPushingEnvironment(author, committer *User, repo *Repository, repoName string, prID int64) []string {
 | 
				
			||||||
	isWiki := "false"
 | 
						isWiki := "false"
 | 
				
			||||||
	if strings.HasSuffix(repo.Name, ".wiki") {
 | 
						if strings.HasSuffix(repoName, ".wiki") {
 | 
				
			||||||
		isWiki = "true"
 | 
							isWiki = "true"
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -32,7 +32,7 @@ func FullPushingEnvironment(author, committer *User, repo *Repository, prID int6
 | 
				
			|||||||
		"GIT_AUTHOR_EMAIL="+authorSig.Email,
 | 
							"GIT_AUTHOR_EMAIL="+authorSig.Email,
 | 
				
			||||||
		"GIT_COMMITTER_NAME="+committerSig.Name,
 | 
							"GIT_COMMITTER_NAME="+committerSig.Name,
 | 
				
			||||||
		"GIT_COMMITTER_EMAIL="+committerSig.Email,
 | 
							"GIT_COMMITTER_EMAIL="+committerSig.Email,
 | 
				
			||||||
		EnvRepoName+"="+repo.Name,
 | 
							EnvRepoName+"="+repoName,
 | 
				
			||||||
		EnvRepoUsername+"="+repo.MustOwnerName(),
 | 
							EnvRepoUsername+"="+repo.MustOwnerName(),
 | 
				
			||||||
		EnvRepoIsWiki+"="+isWiki,
 | 
							EnvRepoIsWiki+"="+isWiki,
 | 
				
			||||||
		EnvPusherName+"="+committer.Name,
 | 
							EnvPusherName+"="+committer.Name,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1835,3 +1835,22 @@ func (issue *Issue) BlockedByDependencies() ([]*Issue, error) {
 | 
				
			|||||||
func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
 | 
					func (issue *Issue) BlockingDependencies() ([]*Issue, error) {
 | 
				
			||||||
	return issue.getBlockingDependencies(x)
 | 
						return issue.getBlockingDependencies(x)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (issue *Issue) updateClosedNum(e Engine) (err error) {
 | 
				
			||||||
 | 
						if issue.IsPull {
 | 
				
			||||||
 | 
							_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
 | 
				
			||||||
 | 
								issue.RepoID,
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								issue.RepoID,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							_, err = e.Exec("UPDATE `repository` SET num_closed_issues=(SELECT count(*) FROM issue WHERE repo_id=? AND is_pull=? AND is_closed=?) WHERE id=?",
 | 
				
			||||||
 | 
								issue.RepoID,
 | 
				
			||||||
 | 
								false,
 | 
				
			||||||
 | 
								true,
 | 
				
			||||||
 | 
								issue.RepoID,
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -142,11 +142,15 @@ func (issue *Issue) ChangeAssignee(doer *User, assigneeID int64) (err error) {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return sess.Commit()
 | 
						if err := sess.Commit(); err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						go HookQueue.Add(issue.RepoID)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (err error) {
 | 
					func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID int64, isCreate bool) (err error) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// Update the assignee
 | 
						// Update the assignee
 | 
				
			||||||
	removed, err := updateIssueAssignee(sess, issue, assigneeID)
 | 
						removed, err := updateIssueAssignee(sess, issue, assigneeID)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
@@ -209,7 +213,6 @@ func (issue *Issue) changeAssignee(sess *xorm.Session, doer *User, assigneeID in
 | 
				
			|||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	go HookQueue.Add(issue.RepoID)
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -632,12 +632,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
 | 
				
			|||||||
			act.OpType = ActionReopenPullRequest
 | 
								act.OpType = ActionReopenPullRequest
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if opts.Issue.IsPull {
 | 
							if err = opts.Issue.updateClosedNum(e); err != nil {
 | 
				
			||||||
			_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls-1 WHERE id=?", opts.Repo.ID)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues-1 WHERE id=?", opts.Repo.ID)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -647,12 +642,7 @@ func sendCreateCommentAction(e *xorm.Session, opts *CreateCommentOptions, commen
 | 
				
			|||||||
			act.OpType = ActionClosePullRequest
 | 
								act.OpType = ActionClosePullRequest
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if opts.Issue.IsPull {
 | 
							if err = opts.Issue.updateClosedNum(e); err != nil {
 | 
				
			||||||
			_, err = e.Exec("UPDATE `repository` SET num_closed_pulls=num_closed_pulls+1 WHERE id=?", opts.Repo.ID)
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			_, err = e.Exec("UPDATE `repository` SET num_closed_issues=num_closed_issues+1 WHERE id=?", opts.Repo.ID)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -189,36 +189,6 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
 | 
				
			|||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch); err != nil {
 | 
					 | 
				
			||||||
		log.Error("pr.BaseRepo.GetBranch[%d]: %v", pr.BaseBranch, err)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if baseCommit, err = baseBranch.GetCommit(); err != nil {
 | 
					 | 
				
			||||||
		log.Error("baseBranch.GetCommit[%d]: %v", pr.ID, err)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch); err != nil {
 | 
					 | 
				
			||||||
		log.Error("pr.HeadRepo.GetBranch[%d]: %v", pr.HeadBranch, err)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if headCommit, err = headBranch.GetCommit(); err != nil {
 | 
					 | 
				
			||||||
		log.Error("headBranch.GetCommit[%d]: %v", pr.ID, err)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	apiBaseBranchInfo := &api.PRBranchInfo{
 | 
					 | 
				
			||||||
		Name:       pr.BaseBranch,
 | 
					 | 
				
			||||||
		Ref:        pr.BaseBranch,
 | 
					 | 
				
			||||||
		Sha:        baseCommit.ID.String(),
 | 
					 | 
				
			||||||
		RepoID:     pr.BaseRepoID,
 | 
					 | 
				
			||||||
		Repository: pr.BaseRepo.innerAPIFormat(e, AccessModeNone, false),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	apiHeadBranchInfo := &api.PRBranchInfo{
 | 
					 | 
				
			||||||
		Name:       pr.HeadBranch,
 | 
					 | 
				
			||||||
		Ref:        pr.HeadBranch,
 | 
					 | 
				
			||||||
		Sha:        headCommit.ID.String(),
 | 
					 | 
				
			||||||
		RepoID:     pr.HeadRepoID,
 | 
					 | 
				
			||||||
		Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = pr.Issue.loadRepo(e); err != nil {
 | 
						if err = pr.Issue.loadRepo(e); err != nil {
 | 
				
			||||||
		log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
 | 
							log.Error("pr.Issue.loadRepo[%d]: %v", pr.ID, err)
 | 
				
			||||||
@@ -227,6 +197,7 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	apiPullRequest := &api.PullRequest{
 | 
						apiPullRequest := &api.PullRequest{
 | 
				
			||||||
		ID:        pr.ID,
 | 
							ID:        pr.ID,
 | 
				
			||||||
 | 
							URL:       pr.Issue.HTMLURL(),
 | 
				
			||||||
		Index:     pr.Index,
 | 
							Index:     pr.Index,
 | 
				
			||||||
		Poster:    apiIssue.Poster,
 | 
							Poster:    apiIssue.Poster,
 | 
				
			||||||
		Title:     apiIssue.Title,
 | 
							Title:     apiIssue.Title,
 | 
				
			||||||
@@ -241,13 +212,68 @@ func (pr *PullRequest) apiFormat(e Engine) *api.PullRequest {
 | 
				
			|||||||
		DiffURL:   pr.Issue.DiffURL(),
 | 
							DiffURL:   pr.Issue.DiffURL(),
 | 
				
			||||||
		PatchURL:  pr.Issue.PatchURL(),
 | 
							PatchURL:  pr.Issue.PatchURL(),
 | 
				
			||||||
		HasMerged: pr.HasMerged,
 | 
							HasMerged: pr.HasMerged,
 | 
				
			||||||
		Base:      apiBaseBranchInfo,
 | 
					 | 
				
			||||||
		Head:      apiHeadBranchInfo,
 | 
					 | 
				
			||||||
		MergeBase: pr.MergeBase,
 | 
							MergeBase: pr.MergeBase,
 | 
				
			||||||
		Deadline:  apiIssue.Deadline,
 | 
							Deadline:  apiIssue.Deadline,
 | 
				
			||||||
		Created:   pr.Issue.CreatedUnix.AsTimePtr(),
 | 
							Created:   pr.Issue.CreatedUnix.AsTimePtr(),
 | 
				
			||||||
		Updated:   pr.Issue.UpdatedUnix.AsTimePtr(),
 | 
							Updated:   pr.Issue.UpdatedUnix.AsTimePtr(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						baseBranch, err = pr.BaseRepo.GetBranch(pr.BaseBranch)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if git.IsErrBranchNotExist(err) {
 | 
				
			||||||
 | 
								apiPullRequest.Base = nil
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								log.Error("GetBranch[%s]: %v", pr.BaseBranch, err)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							apiBaseBranchInfo := &api.PRBranchInfo{
 | 
				
			||||||
 | 
								Name:       pr.BaseBranch,
 | 
				
			||||||
 | 
								Ref:        pr.BaseBranch,
 | 
				
			||||||
 | 
								RepoID:     pr.BaseRepoID,
 | 
				
			||||||
 | 
								Repository: pr.BaseRepo.innerAPIFormat(e, AccessModeNone, false),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							baseCommit, err = baseBranch.GetCommit()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if git.IsErrNotExist(err) {
 | 
				
			||||||
 | 
									apiBaseBranchInfo.Sha = ""
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									log.Error("GetCommit[%s]: %v", baseBranch.Name, err)
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								apiBaseBranchInfo.Sha = baseCommit.ID.String()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							apiPullRequest.Base = apiBaseBranchInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						headBranch, err = pr.HeadRepo.GetBranch(pr.HeadBranch)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if git.IsErrBranchNotExist(err) {
 | 
				
			||||||
 | 
								apiPullRequest.Head = nil
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								log.Error("GetBranch[%s]: %v", pr.HeadBranch, err)
 | 
				
			||||||
 | 
								return nil
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							apiHeadBranchInfo := &api.PRBranchInfo{
 | 
				
			||||||
 | 
								Name:       pr.HeadBranch,
 | 
				
			||||||
 | 
								Ref:        pr.HeadBranch,
 | 
				
			||||||
 | 
								RepoID:     pr.HeadRepoID,
 | 
				
			||||||
 | 
								Repository: pr.HeadRepo.innerAPIFormat(e, AccessModeNone, false),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							headCommit, err = headBranch.GetCommit()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								if git.IsErrNotExist(err) {
 | 
				
			||||||
 | 
									apiHeadBranchInfo.Sha = ""
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									log.Error("GetCommit[%s]: %v", headBranch.Name, err)
 | 
				
			||||||
 | 
									return nil
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								apiHeadBranchInfo.Sha = headCommit.ID.String()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							apiPullRequest.Head = apiHeadBranchInfo
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pr.Status != PullRequestStatusChecking {
 | 
						if pr.Status != PullRequestStatusChecking {
 | 
				
			||||||
		mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
 | 
							mergeable := pr.Status != PullRequestStatusConflict && !pr.IsWorkInProgress()
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,15 @@ func TestPullRequest_LoadIssue(t *testing.T) {
 | 
				
			|||||||
	assert.Equal(t, int64(2), pr.Issue.ID)
 | 
						assert.Equal(t, int64(2), pr.Issue.ID)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO TestPullRequest_APIFormat
 | 
					func TestPullRequest_APIFormat(t *testing.T) {
 | 
				
			||||||
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 | 
						pr := AssertExistsAndLoadBean(t, &PullRequest{ID: 1}).(*PullRequest)
 | 
				
			||||||
 | 
						assert.NoError(t, pr.LoadAttributes())
 | 
				
			||||||
 | 
						assert.NoError(t, pr.LoadIssue())
 | 
				
			||||||
 | 
						apiPullRequest := pr.APIFormat()
 | 
				
			||||||
 | 
						assert.NotNil(t, apiPullRequest)
 | 
				
			||||||
 | 
						assert.Nil(t, apiPullRequest.Head)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPullRequest_GetBaseRepo(t *testing.T) {
 | 
					func TestPullRequest_GetBaseRepo(t *testing.T) {
 | 
				
			||||||
	assert.NoError(t, PrepareTestDatabase())
 | 
						assert.NoError(t, PrepareTestDatabase())
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -134,8 +134,8 @@ type Repository struct {
 | 
				
			|||||||
	Owner         *User  `xorm:"-"`
 | 
						Owner         *User  `xorm:"-"`
 | 
				
			||||||
	LowerName     string `xorm:"UNIQUE(s) INDEX NOT NULL"`
 | 
						LowerName     string `xorm:"UNIQUE(s) INDEX NOT NULL"`
 | 
				
			||||||
	Name          string `xorm:"INDEX NOT NULL"`
 | 
						Name          string `xorm:"INDEX NOT NULL"`
 | 
				
			||||||
	Description   string
 | 
						Description   string `xorm:"TEXT"`
 | 
				
			||||||
	Website       string
 | 
						Website       string `xorm:"VARCHAR(2048)"`
 | 
				
			||||||
	DefaultBranch string
 | 
						DefaultBranch string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	NumWatches          int
 | 
						NumWatches          int
 | 
				
			||||||
@@ -1324,7 +1324,6 @@ func createRepository(e *xorm.Session, doer, u *User, repo *Repository) (err err
 | 
				
			|||||||
		}); err != nil {
 | 
							}); err != nil {
 | 
				
			||||||
			return fmt.Errorf("prepareWebhooks: %v", err)
 | 
								return fmt.Errorf("prepareWebhooks: %v", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		go HookQueue.Add(repo.ID)
 | 
					 | 
				
			||||||
	} else if err = repo.recalculateAccesses(e); err != nil {
 | 
						} else if err = repo.recalculateAccesses(e); err != nil {
 | 
				
			||||||
		// Organization automatically called this in addRepository method.
 | 
							// Organization automatically called this in addRepository method.
 | 
				
			||||||
		return fmt.Errorf("recalculateAccesses: %v", err)
 | 
							return fmt.Errorf("recalculateAccesses: %v", err)
 | 
				
			||||||
@@ -1393,7 +1392,16 @@ func CreateRepository(doer, u *User, opts CreateRepoOptions) (_ *Repository, err
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return repo, sess.Commit()
 | 
						if err = sess.Commit(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add to hook queue for created repo after session commit.
 | 
				
			||||||
 | 
						if u.IsOrganization() {
 | 
				
			||||||
 | 
							go HookQueue.Add(repo.ID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return repo, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func countRepositories(userID int64, private bool) int64 {
 | 
					func countRepositories(userID int64, private bool) int64 {
 | 
				
			||||||
@@ -2327,6 +2335,23 @@ func CheckRepoStats() {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	// ***** END: Repository.NumClosedIssues *****
 | 
						// ***** END: Repository.NumClosedIssues *****
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// ***** START: Repository.NumClosedPulls *****
 | 
				
			||||||
 | 
						desc = "repository count 'num_closed_pulls'"
 | 
				
			||||||
 | 
						results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_closed_pulls!=(SELECT COUNT(*) FROM `issue` WHERE repo_id=repo.id AND is_closed=? AND is_pull=?)", true, true)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error("Select %s: %v", desc, err)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							for _, result := range results {
 | 
				
			||||||
 | 
								id := com.StrTo(result["id"]).MustInt64()
 | 
				
			||||||
 | 
								log.Trace("Updating %s: %d", desc, id)
 | 
				
			||||||
 | 
								_, err = x.Exec("UPDATE `repository` SET num_closed_pulls=(SELECT COUNT(*) FROM `issue` WHERE repo_id=? AND is_closed=? AND is_pull=?) WHERE id=?", id, true, true, id)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Error("Update %s[%d]: %v", desc, id, err)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// ***** END: Repository.NumClosedPulls *****
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FIXME: use checker when stop supporting old fork repo format.
 | 
						// FIXME: use checker when stop supporting old fork repo format.
 | 
				
			||||||
	// ***** START: Repository.NumForks *****
 | 
						// ***** START: Repository.NumForks *****
 | 
				
			||||||
	results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
 | 
						results, err = x.Query("SELECT repo.id FROM `repository` repo WHERE repo.num_forks!=(SELECT COUNT(*) FROM `repository` WHERE fork_id=repo.id)")
 | 
				
			||||||
@@ -2461,6 +2486,11 @@ func ForkRepository(doer, u *User, oldRepo *Repository, name, desc string) (_ *R
 | 
				
			|||||||
		go HookQueue.Add(oldRepo.ID)
 | 
							go HookQueue.Add(oldRepo.ID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Add to hook queue for created repo after session commit.
 | 
				
			||||||
 | 
						if u.IsOrganization() {
 | 
				
			||||||
 | 
							go HookQueue.Add(repo.ID)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err = repo.UpdateSize(); err != nil {
 | 
						if err = repo.UpdateSize(); err != nil {
 | 
				
			||||||
		log.Error("Failed to update size for repository: %v", err)
 | 
							log.Error("Failed to update size for repository: %v", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -195,9 +195,9 @@ func (u *User) UpdateTheme(themeName string) error {
 | 
				
			|||||||
	return UpdateUserCols(u, "theme")
 | 
						return UpdateUserCols(u, "theme")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// getEmail returns an noreply email, if the user has set to keep his
 | 
					// GetEmail returns an noreply email, if the user has set to keep his
 | 
				
			||||||
// email address private, otherwise the primary email address.
 | 
					// email address private, otherwise the primary email address.
 | 
				
			||||||
func (u *User) getEmail() string {
 | 
					func (u *User) GetEmail() string {
 | 
				
			||||||
	if u.KeepEmailPrivate {
 | 
						if u.KeepEmailPrivate {
 | 
				
			||||||
		return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress)
 | 
							return fmt.Sprintf("%s@%s", u.LowerName, setting.Service.NoReplyAddress)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -210,7 +210,7 @@ func (u *User) APIFormat() *api.User {
 | 
				
			|||||||
		ID:        u.ID,
 | 
							ID:        u.ID,
 | 
				
			||||||
		UserName:  u.Name,
 | 
							UserName:  u.Name,
 | 
				
			||||||
		FullName:  u.FullName,
 | 
							FullName:  u.FullName,
 | 
				
			||||||
		Email:     u.getEmail(),
 | 
							Email:     u.GetEmail(),
 | 
				
			||||||
		AvatarURL: u.AvatarLink(),
 | 
							AvatarURL: u.AvatarLink(),
 | 
				
			||||||
		Language:  u.Language,
 | 
							Language:  u.Language,
 | 
				
			||||||
		IsAdmin:   u.IsAdmin,
 | 
							IsAdmin:   u.IsAdmin,
 | 
				
			||||||
@@ -425,7 +425,7 @@ func (u *User) GetFollowing(page int) ([]*User, error) {
 | 
				
			|||||||
func (u *User) NewGitSig() *git.Signature {
 | 
					func (u *User) NewGitSig() *git.Signature {
 | 
				
			||||||
	return &git.Signature{
 | 
						return &git.Signature{
 | 
				
			||||||
		Name:  u.GitName(),
 | 
							Name:  u.GitName(),
 | 
				
			||||||
		Email: u.getEmail(),
 | 
							Email: u.GetEmail(),
 | 
				
			||||||
		When:  time.Now(),
 | 
							When:  time.Now(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -751,6 +751,7 @@ var (
 | 
				
			|||||||
		"robots.txt",
 | 
							"robots.txt",
 | 
				
			||||||
		".",
 | 
							".",
 | 
				
			||||||
		"..",
 | 
							"..",
 | 
				
			||||||
 | 
							".well-known",
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	reservedUserPatterns = []string{"*.keys", "*.gpg"}
 | 
						reservedUserPatterns = []string{"*.keys", "*.gpg"}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -217,7 +217,13 @@ func (repo *Repository) updateWikiPage(doer *User, oldWikiName, newWikiName, con
 | 
				
			|||||||
	if err := git.Push(basePath, git.PushOptions{
 | 
						if err := git.Push(basePath, git.PushOptions{
 | 
				
			||||||
		Remote: "origin",
 | 
							Remote: "origin",
 | 
				
			||||||
		Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
 | 
							Branch: fmt.Sprintf("%s:%s%s", commitHash.String(), git.BranchPrefix, "master"),
 | 
				
			||||||
		Env:    PushingEnvironment(doer, repo),
 | 
							Env: FullPushingEnvironment(
 | 
				
			||||||
 | 
								doer,
 | 
				
			||||||
 | 
								doer,
 | 
				
			||||||
 | 
								repo,
 | 
				
			||||||
 | 
								repo.Name+".wiki",
 | 
				
			||||||
 | 
								0,
 | 
				
			||||||
 | 
							),
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		log.Error("%v", err)
 | 
							log.Error("%v", err)
 | 
				
			||||||
		return fmt.Errorf("Push: %v", err)
 | 
							return fmt.Errorf("Push: %v", err)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,7 +68,9 @@ func (tes Entries) GetCommitsInfo(commit *Commit, treePath string, cache LastCom
 | 
				
			|||||||
	// get it for free during the tree traversal and it's used for listing
 | 
						// get it for free during the tree traversal and it's used for listing
 | 
				
			||||||
	// pages to display information about newest commit for a given path.
 | 
						// pages to display information about newest commit for a given path.
 | 
				
			||||||
	var treeCommit *Commit
 | 
						var treeCommit *Commit
 | 
				
			||||||
	if rev, ok := revs[""]; ok {
 | 
						if treePath == "" {
 | 
				
			||||||
 | 
							treeCommit = commit
 | 
				
			||||||
 | 
						} else if rev, ok := revs[""]; ok {
 | 
				
			||||||
		treeCommit = convertCommit(rev)
 | 
							treeCommit = convertCommit(rev)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return commitsInfo, treeCommit, nil
 | 
						return commitsInfo, treeCommit, nil
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -28,21 +28,27 @@ func cloneRepo(url, dir, name string) (string, error) {
 | 
				
			|||||||
func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
 | 
					func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
 | 
				
			||||||
	// these test case are specific to the repo1 test repo
 | 
						// these test case are specific to the repo1 test repo
 | 
				
			||||||
	testCases := []struct {
 | 
						testCases := []struct {
 | 
				
			||||||
		CommitID    string
 | 
							CommitID           string
 | 
				
			||||||
		Path        string
 | 
							Path               string
 | 
				
			||||||
		ExpectedIDs map[string]string
 | 
							ExpectedIDs        map[string]string
 | 
				
			||||||
 | 
							ExpectedTreeCommit string
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
 | 
							{"8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2", "", map[string]string{
 | 
				
			||||||
			"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
 | 
								"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
 | 
				
			||||||
			"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
 | 
								"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
 | 
				
			||||||
		}},
 | 
							}, "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2"},
 | 
				
			||||||
		{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
 | 
							{"2839944139e0de9737a044f78b0e4b40d989a9e3", "", map[string]string{
 | 
				
			||||||
			"file1.txt":   "2839944139e0de9737a044f78b0e4b40d989a9e3",
 | 
								"file1.txt":   "2839944139e0de9737a044f78b0e4b40d989a9e3",
 | 
				
			||||||
			"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
 | 
								"branch1.txt": "9c9aef8dd84e02bc7ec12641deb4c930a7c30185",
 | 
				
			||||||
		}},
 | 
							}, "2839944139e0de9737a044f78b0e4b40d989a9e3"},
 | 
				
			||||||
		{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
 | 
							{"5c80b0245c1c6f8343fa418ec374b13b5d4ee658", "branch2", map[string]string{
 | 
				
			||||||
			"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
 | 
								"branch2.txt": "5c80b0245c1c6f8343fa418ec374b13b5d4ee658",
 | 
				
			||||||
		}},
 | 
							}, "5c80b0245c1c6f8343fa418ec374b13b5d4ee658"},
 | 
				
			||||||
 | 
							{"feaf4ba6bc635fec442f46ddd4512416ec43c2c2", "", map[string]string{
 | 
				
			||||||
 | 
								"file1.txt": "95bb4d39648ee7e325106df01a621c530863a653",
 | 
				
			||||||
 | 
								"file2.txt": "8d92fc957a4d7cfd98bc375f0b7bb189a0d6c9f2",
 | 
				
			||||||
 | 
								"foo":       "37991dec2c8e592043f47155ce4808d4580f9123",
 | 
				
			||||||
 | 
							}, "feaf4ba6bc635fec442f46ddd4512416ec43c2c2"},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for _, testCase := range testCases {
 | 
						for _, testCase := range testCases {
 | 
				
			||||||
		commit, err := repo1.GetCommit(testCase.CommitID)
 | 
							commit, err := repo1.GetCommit(testCase.CommitID)
 | 
				
			||||||
@@ -51,7 +57,8 @@ func testGetCommitsInfo(t *testing.T, repo1 *Repository) {
 | 
				
			|||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		entries, err := tree.ListEntries()
 | 
							entries, err := tree.ListEntries()
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		commitsInfo, _, err := entries.GetCommitsInfo(commit, testCase.Path, nil)
 | 
							commitsInfo, treeCommit, err := entries.GetCommitsInfo(commit, testCase.Path, nil)
 | 
				
			||||||
 | 
							assert.Equal(t, testCase.ExpectedTreeCommit, treeCommit.ID.String())
 | 
				
			||||||
		assert.NoError(t, err)
 | 
							assert.NoError(t, err)
 | 
				
			||||||
		assert.Len(t, commitsInfo, len(testCase.ExpectedIDs))
 | 
							assert.Len(t, commitsInfo, len(testCase.ExpectedIDs))
 | 
				
			||||||
		for _, commitInfo := range commitsInfo {
 | 
							for _, commitInfo := range commitsInfo {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,12 +23,12 @@ func TestRepository_GetCodeActivityStats(t *testing.T) {
 | 
				
			|||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	assert.NotNil(t, code)
 | 
						assert.NotNil(t, code)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	assert.EqualValues(t, 8, code.CommitCount)
 | 
						assert.EqualValues(t, 9, code.CommitCount)
 | 
				
			||||||
	assert.EqualValues(t, 2, code.AuthorCount)
 | 
						assert.EqualValues(t, 3, code.AuthorCount)
 | 
				
			||||||
	assert.EqualValues(t, 8, code.CommitCountInAllBranches)
 | 
						assert.EqualValues(t, 9, code.CommitCountInAllBranches)
 | 
				
			||||||
	assert.EqualValues(t, 10, code.Additions)
 | 
						assert.EqualValues(t, 10, code.Additions)
 | 
				
			||||||
	assert.EqualValues(t, 1, code.Deletions)
 | 
						assert.EqualValues(t, 1, code.Deletions)
 | 
				
			||||||
	assert.Len(t, code.Authors, 2)
 | 
						assert.Len(t, code.Authors, 3)
 | 
				
			||||||
	assert.Contains(t, code.Authors, "tris.git@shoddynet.org")
 | 
						assert.Contains(t, code.Authors, "tris.git@shoddynet.org")
 | 
				
			||||||
	assert.EqualValues(t, 3, code.Authors["tris.git@shoddynet.org"])
 | 
						assert.EqualValues(t, 3, code.Authors["tris.git@shoddynet.org"])
 | 
				
			||||||
	assert.EqualValues(t, 5, code.Authors[""])
 | 
						assert.EqualValues(t, 5, code.Authors[""])
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								modules/git/tests/repos/repo1_bare/logs/HEAD
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								modules/git/tests/repos/repo1_bare/logs/HEAD
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200	push
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					37991dec2c8e592043f47155ce4808d4580f9123 feaf4ba6bc635fec442f46ddd4512416ec43c2c2 silverwind <me@silverwind.io> 1563741799 +0200	push
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							@@ -1 +1 @@
 | 
				
			|||||||
37991dec2c8e592043f47155ce4808d4580f9123
 | 
					feaf4ba6bc635fec442f46ddd4512416ec43c2c2
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -153,7 +153,7 @@ func RenderRaw(body []byte, urlPrefix string, wikiMarkdown bool) []byte {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	body = blackfriday.Markdown(body, renderer, exts)
 | 
						body = blackfriday.Markdown(body, renderer, exts)
 | 
				
			||||||
	return body
 | 
						return markup.SanitizeBytes(body)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -111,7 +111,7 @@ func (g *GiteaLocalUploader) CreateMilestones(milestones ...*base.Milestone) err
 | 
				
			|||||||
			RepoID:       g.repo.ID,
 | 
								RepoID:       g.repo.ID,
 | 
				
			||||||
			Name:         milestone.Title,
 | 
								Name:         milestone.Title,
 | 
				
			||||||
			Content:      milestone.Description,
 | 
								Content:      milestone.Description,
 | 
				
			||||||
			IsClosed:     milestone.State == "close",
 | 
								IsClosed:     milestone.State == "closed",
 | 
				
			||||||
			DeadlineUnix: deadline,
 | 
								DeadlineUnix: deadline,
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ms.IsClosed && milestone.Closed != nil {
 | 
							if ms.IsClosed && milestone.Closed != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -173,6 +173,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		closed1 = time.Date(2018, 10, 23, 02, 57, 43, 0, time.UTC)
 | 
							closed1 = time.Date(2018, 10, 23, 02, 57, 43, 0, time.UTC)
 | 
				
			||||||
 | 
							closed7 = time.Date(2019, 7, 8, 8, 20, 23, 0, time.UTC)
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	assert.EqualValues(t, []*base.Issue{
 | 
						assert.EqualValues(t, []*base.Issue{
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
@@ -208,9 +209,9 @@ func TestGitHubDownloadRepo(t *testing.T) {
 | 
				
			|||||||
			Number:     7,
 | 
								Number:     7,
 | 
				
			||||||
			Title:      "display page revisions on wiki",
 | 
								Title:      "display page revisions on wiki",
 | 
				
			||||||
			Content:    "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991",
 | 
								Content:    "Hi guys,\r\n\r\nWiki on Gogs is very fine, I liked a lot, but I think that is good idea to be possible see other revisions from page as a page history.\r\n\r\nWhat you think?\r\n\r\nReference: https://github.com/gogits/gogs/issues/2991",
 | 
				
			||||||
			Milestone:  "1.x.x",
 | 
								Milestone:  "1.10.0",
 | 
				
			||||||
			PosterName: "joubertredrat",
 | 
								PosterName: "joubertredrat",
 | 
				
			||||||
			State:      "open",
 | 
								State:      "closed",
 | 
				
			||||||
			Created:    time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC),
 | 
								Created:    time.Date(2016, 11, 02, 18, 57, 32, 0, time.UTC),
 | 
				
			||||||
			Labels: []*base.Label{
 | 
								Labels: []*base.Label{
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
@@ -232,6 +233,7 @@ func TestGitHubDownloadRepo(t *testing.T) {
 | 
				
			|||||||
				Heart:      0,
 | 
									Heart:      0,
 | 
				
			||||||
				Hooray:     0,
 | 
									Hooray:     0,
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								Closed: &closed7,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			Number:     8,
 | 
								Number:     8,
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,6 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	defer func() {
 | 
						defer func() {
 | 
				
			||||||
		go models.HookQueue.Add(pr.BaseRepo.ID)
 | 
					 | 
				
			||||||
		go models.AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
 | 
							go models.AddTestPullRequestTask(doer, pr.BaseRepo.ID, pr.BaseBranch, false)
 | 
				
			||||||
	}()
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -102,7 +101,7 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Fetch head branch
 | 
						// Fetch head branch
 | 
				
			||||||
	if err := git.NewCommand("fetch", remoteRepoName).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
 | 
						if err := git.NewCommand("fetch", remoteRepoName, pr.HeadBranch).RunInDirPipeline(tmpBasePath, nil, &errbuf); err != nil {
 | 
				
			||||||
		return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
 | 
							return fmt.Errorf("git fetch [%s -> %s]: %s", headRepoPath, tmpBasePath, errbuf.String())
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -241,7 +240,13 @@ func Merge(pr *models.PullRequest, doer *models.User, baseGitRepo *git.Repositor
 | 
				
			|||||||
		headUser = doer
 | 
							headUser = doer
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	env := models.FullPushingEnvironment(headUser, doer, pr.BaseRepo, pr.ID)
 | 
						env := models.FullPushingEnvironment(
 | 
				
			||||||
 | 
							headUser,
 | 
				
			||||||
 | 
							doer,
 | 
				
			||||||
 | 
							pr.BaseRepo,
 | 
				
			||||||
 | 
							pr.BaseRepo.Name,
 | 
				
			||||||
 | 
							pr.ID,
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Push back to upstream.
 | 
						// Push back to upstream.
 | 
				
			||||||
	if err := git.NewCommand("push", "origin", pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
 | 
						if err := git.NewCommand("push", "origin", pr.BaseBranch).RunInDirTimeoutEnvPipeline(env, -1, tmpBasePath, nil, &errbuf); err != nil {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -694,6 +694,7 @@ editor.delete = Delete '%s'
 | 
				
			|||||||
editor.commit_message_desc = Add an optional extended description…
 | 
					editor.commit_message_desc = Add an optional extended description…
 | 
				
			||||||
editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
 | 
					editor.commit_directly_to_this_branch = Commit directly to the <strong class="branch-name">%s</strong> branch.
 | 
				
			||||||
editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
 | 
					editor.create_new_branch = Create a <strong>new branch</strong> for this commit and start a pull request.
 | 
				
			||||||
 | 
					editor.propose_file_change = Propose file change
 | 
				
			||||||
editor.new_branch_name_desc = New branch name…
 | 
					editor.new_branch_name_desc = New branch name…
 | 
				
			||||||
editor.cancel = Cancel
 | 
					editor.cancel = Cancel
 | 
				
			||||||
editor.filename_cannot_be_empty = The filename cannot be empty.
 | 
					editor.filename_cannot_be_empty = The filename cannot be empty.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -208,6 +208,9 @@ footer .ui.left,footer .ui.right{line-height:40px}
 | 
				
			|||||||
.ui.tabular.menu .item{color:rgba(0,0,0,.5)}
 | 
					.ui.tabular.menu .item{color:rgba(0,0,0,.5)}
 | 
				
			||||||
.ui.tabular.menu .item:hover{color:rgba(0,0,0,.8)}
 | 
					.ui.tabular.menu .item:hover{color:rgba(0,0,0,.8)}
 | 
				
			||||||
.ui.tabular.menu .item.active{color:rgba(0,0,0,.9)}
 | 
					.ui.tabular.menu .item.active{color:rgba(0,0,0,.9)}
 | 
				
			||||||
 | 
					.inline-grouped-list{display:inline-block;vertical-align:top}
 | 
				
			||||||
 | 
					.inline-grouped-list>.ui{display:block;margin-top:5px;margin-bottom:10px}
 | 
				
			||||||
 | 
					.inline-grouped-list>.ui:first-child{margin-top:1px}
 | 
				
			||||||
.markdown:not(code){overflow:hidden;font-size:16px;line-height:1.6!important;word-wrap:break-word}
 | 
					.markdown:not(code){overflow:hidden;font-size:16px;line-height:1.6!important;word-wrap:break-word}
 | 
				
			||||||
.markdown:not(code).ui.segment{padding:3em}
 | 
					.markdown:not(code).ui.segment{padding:3em}
 | 
				
			||||||
.markdown:not(code).file-view{padding:2em 2em 2em!important}
 | 
					.markdown:not(code).file-view{padding:2em 2em 2em!important}
 | 
				
			||||||
@@ -744,7 +747,7 @@ footer .ui.left,footer .ui.right{line-height:40px}
 | 
				
			|||||||
.repository .segment.reactions .select-reaction{float:none}
 | 
					.repository .segment.reactions .select-reaction{float:none}
 | 
				
			||||||
.repository .segment.reactions .select-reaction:not(.active) a{display:none}
 | 
					.repository .segment.reactions .select-reaction:not(.active) a{display:none}
 | 
				
			||||||
.repository .segment.reactions:hover .select-reaction a{display:block}
 | 
					.repository .segment.reactions:hover .select-reaction a{display:block}
 | 
				
			||||||
.user-cards .list{padding:0}
 | 
					.user-cards .list{padding:0;display:flex;flex-wrap:wrap}
 | 
				
			||||||
.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}
 | 
					.user-cards .list .item{list-style:none;width:32%;margin:10px 10px 10px 0;padding-bottom:14px;float:left}
 | 
				
			||||||
.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}
 | 
					.user-cards .list .item .avatar{width:48px;height:48px;float:left;display:block;margin-right:10px}
 | 
				
			||||||
.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}
 | 
					.user-cards .list .item .name{margin-top:0;margin-bottom:0;font-weight:400}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -209,7 +209,7 @@ a.ui.label:hover,a.ui.labels .label:hover{background-color:#505667;color:#dbdbdb
 | 
				
			|||||||
.repository .label.list .item{border-bottom:1px dashed #4c505c}
 | 
					.repository .label.list .item{border-bottom:1px dashed #4c505c}
 | 
				
			||||||
.ui.basic.blue.button,.ui.basic.blue.buttons .button{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
 | 
					.ui.basic.blue.button,.ui.basic.blue.buttons .button{box-shadow:0 0 0 1px #87ab63 inset!important;color:#87ab63!important}
 | 
				
			||||||
.repository.file.list #file-content .code-view .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
 | 
					.repository.file.list #file-content .code-view .hljs,.repository.file.list #file-content .code-view .lines-code ol,.repository.file.list #file-content .code-view .lines-code pre,.repository.file.list #file-content .code-view .lines-num .hljs,.repository.file.list #file-content .code-view .lines-num ol,.repository.file.list #file-content .code-view .lines-num pre{background-color:#2a2e3a}
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6){background-color:#2a2e3a}
 | 
					.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6){background-color:#2a2e3a}
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(6){background-color:#283e2d!important;border-color:#314a37!important}
 | 
					.repository .diff-file-box .code-diff-split tbody tr td.add-code,.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(4),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(5),.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(6){background-color:#283e2d!important;border-color:#314a37!important}
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3){background-color:#3c2626!important;border-color:#634343!important}
 | 
					.repository .diff-file-box .code-diff-split tbody tr td.del-code,.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(1),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(2),.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3){background-color:#3c2626!important;border-color:#634343!important}
 | 
				
			||||||
.ui.blue.button:active,.ui.blue.buttons .button:active{background-color:#a27558}
 | 
					.ui.blue.button:active,.ui.blue.buttons .button:active{background-color:#a27558}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,6 +10,11 @@ function htmlEncode(text) {
 | 
				
			|||||||
var csrf;
 | 
					var csrf;
 | 
				
			||||||
var suburl;
 | 
					var suburl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Disable Dropzone auto-discover because it's manually initialized
 | 
				
			||||||
 | 
					if (typeof(Dropzone) !== "undefined") {
 | 
				
			||||||
 | 
					    Dropzone.autoDiscover = false;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Polyfill for IE9+ support (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
 | 
					// Polyfill for IE9+ support (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
 | 
				
			||||||
if (!Array.from) {
 | 
					if (!Array.from) {
 | 
				
			||||||
    Array.from = (function () {
 | 
					    Array.from = (function () {
 | 
				
			||||||
@@ -1270,6 +1275,7 @@ function initEditor() {
 | 
				
			|||||||
            $('.quick-pull-branch-name').hide();
 | 
					            $('.quick-pull-branch-name').hide();
 | 
				
			||||||
            $('.quick-pull-branch-name input').prop('required',false);
 | 
					            $('.quick-pull-branch-name input').prop('required',false);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					        $('#commit-button').text($(this).attr('button_text'));
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    var $editFilename = $("#file-name");
 | 
					    var $editFilename = $("#file-name");
 | 
				
			||||||
@@ -1968,17 +1974,18 @@ $(document).ready(function () {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Highlight JS
 | 
					    // Highlight JS
 | 
				
			||||||
    if (typeof hljs != 'undefined') {
 | 
					    if (typeof hljs != 'undefined') {
 | 
				
			||||||
        hljs.initHighlightingOnLoad();
 | 
					        const nodes = [].slice.call(document.querySelectorAll('pre code') || []);
 | 
				
			||||||
 | 
					        for (let i = 0; i < nodes.length; i++) {
 | 
				
			||||||
 | 
					            hljs.highlightBlock(nodes[i]);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Dropzone
 | 
					    // Dropzone
 | 
				
			||||||
    var $dropzone = $('#dropzone');
 | 
					    const $dropzone = $('#dropzone');
 | 
				
			||||||
    if ($dropzone.length > 0) {
 | 
					    if ($dropzone.length > 0) {
 | 
				
			||||||
        // Disable auto discover for all elements:
 | 
					        const filenameDict = {};
 | 
				
			||||||
        Dropzone.autoDiscover = false;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        var filenameDict = {};
 | 
					        new Dropzone("#dropzone", {
 | 
				
			||||||
        $dropzone.dropzone({
 | 
					 | 
				
			||||||
            url: $dropzone.data('upload-url'),
 | 
					            url: $dropzone.data('upload-url'),
 | 
				
			||||||
            headers: {"X-Csrf-Token": csrf},
 | 
					            headers: {"X-Csrf-Token": csrf},
 | 
				
			||||||
            maxFiles: $dropzone.data('max-file'),
 | 
					            maxFiles: $dropzone.data('max-file'),
 | 
				
			||||||
@@ -2006,7 +2013,7 @@ $(document).ready(function () {
 | 
				
			|||||||
                        });
 | 
					                        });
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                })
 | 
					                })
 | 
				
			||||||
            }
 | 
					            },
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2104,12 +2111,16 @@ $(document).ready(function () {
 | 
				
			|||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    $('.issue-action').click(function () {
 | 
					    $('.issue-action').click(function () {
 | 
				
			||||||
        var action = this.dataset.action
 | 
					        let action = this.dataset.action;
 | 
				
			||||||
        var elementId = this.dataset.elementId
 | 
					        let elementId = this.dataset.elementId;
 | 
				
			||||||
        var issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
 | 
					        let issueIDs = $('.issue-checkbox').children('input:checked').map(function() {
 | 
				
			||||||
            return this.dataset.issueId;
 | 
					            return this.dataset.issueId;
 | 
				
			||||||
        }).get().join();
 | 
					        }).get().join();
 | 
				
			||||||
        var url = this.dataset.url
 | 
					        let url = this.dataset.url;
 | 
				
			||||||
 | 
					        if (elementId === '0' && url.substr(-9) === '/assignee'){
 | 
				
			||||||
 | 
					            elementId = '';
 | 
				
			||||||
 | 
					            action = 'clear';
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        updateIssuesMeta(url, action, issueIDs, elementId).then(reload);
 | 
					        updateIssuesMeta(url, action, issueIDs, elementId).then(reload);
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -605,7 +605,6 @@ code,
 | 
				
			|||||||
.file-comment {
 | 
					.file-comment {
 | 
				
			||||||
    font: 12px @monospaced-fonts, monospace;
 | 
					    font: 12px @monospaced-fonts, monospace;
 | 
				
			||||||
    color: rgba(0, 0, 0, 0.87);
 | 
					    color: rgba(0, 0, 0, 0.87);
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ui.floating.dropdown {
 | 
					.ui.floating.dropdown {
 | 
				
			||||||
@@ -877,3 +876,19 @@ footer {
 | 
				
			|||||||
.ui.tabular.menu .item.active {
 | 
					.ui.tabular.menu .item.active {
 | 
				
			||||||
    color: rgba(0, 0, 0, 0.9);
 | 
					    color: rgba(0, 0, 0, 0.9);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* multiple radio or checkboxes as inline element */
 | 
				
			||||||
 | 
					.inline-grouped-list {
 | 
				
			||||||
 | 
					    display: inline-block;
 | 
				
			||||||
 | 
					    vertical-align: top;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    > .ui {
 | 
				
			||||||
 | 
					        display: block;
 | 
				
			||||||
 | 
					        margin-top: 5px;
 | 
				
			||||||
 | 
					        margin-bottom: 10px;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        &:first-child {
 | 
				
			||||||
 | 
					            margin-top: 1px;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1971,6 +1971,8 @@
 | 
				
			|||||||
&.user-cards {
 | 
					&.user-cards {
 | 
				
			||||||
    .list {
 | 
					    .list {
 | 
				
			||||||
        padding: 0;
 | 
					        padding: 0;
 | 
				
			||||||
 | 
					        display: flex;
 | 
				
			||||||
 | 
					        flex-wrap: wrap;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        .item {
 | 
					        .item {
 | 
				
			||||||
            list-style: none;
 | 
					            list-style: none;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1082,7 +1082,7 @@ a.ui.labels .label:hover {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
 | 
					.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(1),
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
 | 
					.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(2),
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(3),
 | 
					.repository .diff-file-box .code-diff-split tbody tr.add-code td:nth-child(3),
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),
 | 
					.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(4),
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),
 | 
					.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(5),
 | 
				
			||||||
.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6) {
 | 
					.repository .diff-file-box .code-diff-split tbody tr.del-code td:nth-child(6) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								public/vendor/VERSIONS
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								public/vendor/VERSIONS
									
									
									
									
										vendored
									
									
								
							@@ -6,7 +6,10 @@ File(s): /vendor/plugins/jquery.areyousure/jquery.are-you-sure.js
 | 
				
			|||||||
Version: 1.9.0
 | 
					Version: 1.9.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
File(s): /vendor/plugins/jquery/jquery.min.js
 | 
					File(s): /vendor/plugins/jquery/jquery.min.js
 | 
				
			||||||
Version: 1.12.4
 | 
					Version: 3.4.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					File(s): /vendor/plugins/jquery-migrate/jquery-migrate.min.js
 | 
				
			||||||
 | 
					Version: 3.0.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
File(s): /vendor/plugins/semantic/semantic.min.js
 | 
					File(s): /vendor/plugins/semantic/semantic.min.js
 | 
				
			||||||
Version: 2.3.1
 | 
					Version: 2.3.1
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										9
									
								
								public/vendor/librejs.html
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										9
									
								
								public/vendor/librejs.html
									
									
									
									
										vendored
									
									
								
							@@ -17,8 +17,13 @@
 | 
				
			|||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
          <td><a href="./plugins/jquery/jquery.min.js">jquery.min.js</a></td>
 | 
					          <td><a href="./plugins/jquery/jquery.min.js">jquery.min.js</a></td>
 | 
				
			||||||
          <td><a href="http://www.freebsd.org/copyright/freebsd-license.html">Expat</a></td>
 | 
					          <td><a href="https://jquery.org/license/">MIT</a></td>
 | 
				
			||||||
          <td><a href="https://code.jquery.com/jquery-1.12.4.min.js">jquery-1.12.4.min.js</a></td>
 | 
					          <td><a href="https://code.jquery.com/jquery-3.4.1.min.js">jquery-3.4.1.min.js</a></td>
 | 
				
			||||||
 | 
					        </tr>
 | 
				
			||||||
 | 
					        <tr>
 | 
				
			||||||
 | 
					          <td><a href="./plugins/jquery-migrate/jquery-migrate.min.js">jquery-migrate.min.js</a></td>
 | 
				
			||||||
 | 
					          <td><a href="https://jquery.org/license/">MIT</a></td>
 | 
				
			||||||
 | 
					          <td><a href="https://code.jquery.com/jquery-migrate-3.0.1.min.js">jquery-migrate-3.0.1.min.js</a></td>
 | 
				
			||||||
        </tr>
 | 
					        </tr>
 | 
				
			||||||
        <tr>
 | 
					        <tr>
 | 
				
			||||||
          <td><a href="./plugins/semantic/semantic.min.js">semantic.min.js</a></td>
 | 
					          <td><a href="./plugins/semantic/semantic.min.js">semantic.min.js</a></td>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										215
									
								
								public/vendor/plugins/jquery-migrate/jquery-migrate.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								public/vendor/plugins/jquery-migrate/jquery-migrate.min.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,215 @@
 | 
				
			|||||||
 | 
					/*! jQuery Migrate v3.0.1 | (c) jQuery Foundation and other contributors | jquery.org/license */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void 0 === jQuery.migrateMute && (jQuery.migrateMute = !0), function(e) {
 | 
				
			||||||
 | 
					    "function" == typeof define && define.amd ? define([ "jquery" ], window, e) : "object" == typeof module && module.exports ? module.exports = e(require("jquery"), window) : e(jQuery, window);
 | 
				
			||||||
 | 
					}(function(e, t) {
 | 
				
			||||||
 | 
					    "use strict";
 | 
				
			||||||
 | 
					    function r(r) {
 | 
				
			||||||
 | 
					        var n = t.console;
 | 
				
			||||||
 | 
					        o[r] || (o[r] = !0, e.migrateWarnings.push(r), n && n.warn && !e.migrateMute && (n.warn("JQMIGRATE: " + r), 
 | 
				
			||||||
 | 
					        e.migrateTrace && n.trace && n.trace()));
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    function n(e, t, n, a) {
 | 
				
			||||||
 | 
					        Object.defineProperty(e, t, {
 | 
				
			||||||
 | 
					            configurable: !0,
 | 
				
			||||||
 | 
					            enumerable: !0,
 | 
				
			||||||
 | 
					            get: function() {
 | 
				
			||||||
 | 
					                return r(a), n;
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            set: function(e) {
 | 
				
			||||||
 | 
					                r(a), n = e;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    function a(e, t, n, a) {
 | 
				
			||||||
 | 
					        e[t] = function() {
 | 
				
			||||||
 | 
					            return r(a), n.apply(this, arguments);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    e.migrateVersion = "3.0.1", function() {
 | 
				
			||||||
 | 
					        var r = /^[12]\./;
 | 
				
			||||||
 | 
					        t.console && t.console.log && (e && !r.test(e.fn.jquery) || t.console.log("JQMIGRATE: jQuery 3.0.0+ REQUIRED"), 
 | 
				
			||||||
 | 
					        e.migrateWarnings && t.console.log("JQMIGRATE: Migrate plugin loaded multiple times"), 
 | 
				
			||||||
 | 
					        t.console.log("JQMIGRATE: Migrate is installed" + (e.migrateMute ? "" : " with logging active") + ", version " + e.migrateVersion));
 | 
				
			||||||
 | 
					    }();
 | 
				
			||||||
 | 
					    var o = {};
 | 
				
			||||||
 | 
					    e.migrateWarnings = [], void 0 === e.migrateTrace && (e.migrateTrace = !0), e.migrateReset = function() {
 | 
				
			||||||
 | 
					        o = {}, e.migrateWarnings.length = 0;
 | 
				
			||||||
 | 
					    }, "BackCompat" === t.document.compatMode && r("jQuery is not compatible with Quirks Mode");
 | 
				
			||||||
 | 
					    var i = e.fn.init, s = e.isNumeric, u = e.find, c = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/, l = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
 | 
				
			||||||
 | 
					    e.fn.init = function(e) {
 | 
				
			||||||
 | 
					        var t = Array.prototype.slice.call(arguments);
 | 
				
			||||||
 | 
					        return "string" == typeof e && "#" === e && (r("jQuery( '#' ) is not a valid selector"), 
 | 
				
			||||||
 | 
					        t[0] = []), i.apply(this, t);
 | 
				
			||||||
 | 
					    }, e.fn.init.prototype = e.fn, e.find = function(e) {
 | 
				
			||||||
 | 
					        var n = Array.prototype.slice.call(arguments);
 | 
				
			||||||
 | 
					        if ("string" == typeof e && c.test(e)) try {
 | 
				
			||||||
 | 
					            t.document.querySelector(e);
 | 
				
			||||||
 | 
					        } catch (a) {
 | 
				
			||||||
 | 
					            e = e.replace(l, function(e, t, r, n) {
 | 
				
			||||||
 | 
					                return "[" + t + r + '"' + n + '"]';
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					            try {
 | 
				
			||||||
 | 
					                t.document.querySelector(e), r("Attribute selector with '#' must be quoted: " + n[0]), 
 | 
				
			||||||
 | 
					                n[0] = e;
 | 
				
			||||||
 | 
					            } catch (e) {
 | 
				
			||||||
 | 
					                r("Attribute selector with '#' was not fixed: " + n[0]);
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return u.apply(this, n);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var d;
 | 
				
			||||||
 | 
					    for (d in u) Object.prototype.hasOwnProperty.call(u, d) && (e.find[d] = u[d]);
 | 
				
			||||||
 | 
					    e.fn.size = function() {
 | 
				
			||||||
 | 
					        return r("jQuery.fn.size() is deprecated and removed; use the .length property"), 
 | 
				
			||||||
 | 
					        this.length;
 | 
				
			||||||
 | 
					    }, e.parseJSON = function() {
 | 
				
			||||||
 | 
					        return r("jQuery.parseJSON is deprecated; use JSON.parse"), JSON.parse.apply(null, arguments);
 | 
				
			||||||
 | 
					    }, e.isNumeric = function(t) {
 | 
				
			||||||
 | 
					        var n = s(t), a = function(t) {
 | 
				
			||||||
 | 
					            var r = t && t.toString();
 | 
				
			||||||
 | 
					            return !e.isArray(t) && r - parseFloat(r) + 1 >= 0;
 | 
				
			||||||
 | 
					        }(t);
 | 
				
			||||||
 | 
					        return n !== a && r("jQuery.isNumeric() should not be called on constructed objects"), 
 | 
				
			||||||
 | 
					        a;
 | 
				
			||||||
 | 
					    }, a(e, "holdReady", e.holdReady, "jQuery.holdReady is deprecated"), a(e, "unique", e.uniqueSort, "jQuery.unique is deprecated; use jQuery.uniqueSort"), 
 | 
				
			||||||
 | 
					    n(e.expr, "filters", e.expr.pseudos, "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos"), 
 | 
				
			||||||
 | 
					    n(e.expr, ":", e.expr.pseudos, "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos");
 | 
				
			||||||
 | 
					    var p = e.ajax;
 | 
				
			||||||
 | 
					    e.ajax = function() {
 | 
				
			||||||
 | 
					        var e = p.apply(this, arguments);
 | 
				
			||||||
 | 
					        return e.promise && (a(e, "success", e.done, "jQXHR.success is deprecated and removed"), 
 | 
				
			||||||
 | 
					        a(e, "error", e.fail, "jQXHR.error is deprecated and removed"), a(e, "complete", e.always, "jQXHR.complete is deprecated and removed")), 
 | 
				
			||||||
 | 
					        e;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var f = e.fn.removeAttr, y = e.fn.toggleClass, m = /\S+/g;
 | 
				
			||||||
 | 
					    e.fn.removeAttr = function(t) {
 | 
				
			||||||
 | 
					        var n = this;
 | 
				
			||||||
 | 
					        return e.each(t.match(m), function(t, a) {
 | 
				
			||||||
 | 
					            e.expr.match.bool.test(a) && (r("jQuery.fn.removeAttr no longer sets boolean properties: " + a), 
 | 
				
			||||||
 | 
					            n.prop(a, !1));
 | 
				
			||||||
 | 
					        }), f.apply(this, arguments);
 | 
				
			||||||
 | 
					    }, e.fn.toggleClass = function(t) {
 | 
				
			||||||
 | 
					        return void 0 !== t && "boolean" != typeof t ? y.apply(this, arguments) : (r("jQuery.fn.toggleClass( boolean ) is deprecated"), 
 | 
				
			||||||
 | 
					        this.each(function() {
 | 
				
			||||||
 | 
					            var r = this.getAttribute && this.getAttribute("class") || "";
 | 
				
			||||||
 | 
					            r && e.data(this, "__className__", r), this.setAttribute && this.setAttribute("class", r || !1 === t ? "" : e.data(this, "__className__") || "");
 | 
				
			||||||
 | 
					        }));
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var h = !1;
 | 
				
			||||||
 | 
					    e.swap && e.each([ "height", "width", "reliableMarginRight" ], function(t, r) {
 | 
				
			||||||
 | 
					        var n = e.cssHooks[r] && e.cssHooks[r].get;
 | 
				
			||||||
 | 
					        n && (e.cssHooks[r].get = function() {
 | 
				
			||||||
 | 
					            var e;
 | 
				
			||||||
 | 
					            return h = !0, e = n.apply(this, arguments), h = !1, e;
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }), e.swap = function(e, t, n, a) {
 | 
				
			||||||
 | 
					        var o, i, s = {};
 | 
				
			||||||
 | 
					        h || r("jQuery.swap() is undocumented and deprecated");
 | 
				
			||||||
 | 
					        for (i in t) s[i] = e.style[i], e.style[i] = t[i];
 | 
				
			||||||
 | 
					        o = n.apply(e, a || []);
 | 
				
			||||||
 | 
					        for (i in t) e.style[i] = s[i];
 | 
				
			||||||
 | 
					        return o;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var g = e.data;
 | 
				
			||||||
 | 
					    e.data = function(t, n, a) {
 | 
				
			||||||
 | 
					        var o;
 | 
				
			||||||
 | 
					        if (n && "object" == typeof n && 2 === arguments.length) {
 | 
				
			||||||
 | 
					            o = e.hasData(t) && g.call(this, t);
 | 
				
			||||||
 | 
					            var i = {};
 | 
				
			||||||
 | 
					            for (var s in n) s !== e.camelCase(s) ? (r("jQuery.data() always sets/gets camelCased names: " + s), 
 | 
				
			||||||
 | 
					            o[s] = n[s]) : i[s] = n[s];
 | 
				
			||||||
 | 
					            return g.call(this, t, i), n;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        return n && "string" == typeof n && n !== e.camelCase(n) && (o = e.hasData(t) && g.call(this, t)) && n in o ? (r("jQuery.data() always sets/gets camelCased names: " + n), 
 | 
				
			||||||
 | 
					        arguments.length > 2 && (o[n] = a), o[n]) : g.apply(this, arguments);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var v = e.Tween.prototype.run, j = function(e) {
 | 
				
			||||||
 | 
					        return e;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    e.Tween.prototype.run = function() {
 | 
				
			||||||
 | 
					        e.easing[this.easing].length > 1 && (r("'jQuery.easing." + this.easing.toString() + "' should use only one argument"), 
 | 
				
			||||||
 | 
					        e.easing[this.easing] = j), v.apply(this, arguments);
 | 
				
			||||||
 | 
					    }, e.fx.interval = e.fx.interval || 13, t.requestAnimationFrame && n(e.fx, "interval", e.fx.interval, "jQuery.fx.interval is deprecated");
 | 
				
			||||||
 | 
					    var Q = e.fn.load, b = e.event.add, w = e.event.fix;
 | 
				
			||||||
 | 
					    e.event.props = [], e.event.fixHooks = {}, n(e.event.props, "concat", e.event.props.concat, "jQuery.event.props.concat() is deprecated and removed"), 
 | 
				
			||||||
 | 
					    e.event.fix = function(t) {
 | 
				
			||||||
 | 
					        var n, a = t.type, o = this.fixHooks[a], i = e.event.props;
 | 
				
			||||||
 | 
					        if (i.length) for (r("jQuery.event.props are deprecated and removed: " + i.join()); i.length; ) e.event.addProp(i.pop());
 | 
				
			||||||
 | 
					        if (o && !o._migrated_ && (o._migrated_ = !0, r("jQuery.event.fixHooks are deprecated and removed: " + a), 
 | 
				
			||||||
 | 
					        (i = o.props) && i.length)) for (;i.length; ) e.event.addProp(i.pop());
 | 
				
			||||||
 | 
					        return n = w.call(this, t), o && o.filter ? o.filter(n, t) : n;
 | 
				
			||||||
 | 
					    }, e.event.add = function(e, n) {
 | 
				
			||||||
 | 
					        return e === t && "load" === n && "complete" === t.document.readyState && r("jQuery(window).on('load'...) called after load event occurred"), 
 | 
				
			||||||
 | 
					        b.apply(this, arguments);
 | 
				
			||||||
 | 
					    }, e.each([ "load", "unload", "error" ], function(t, n) {
 | 
				
			||||||
 | 
					        e.fn[n] = function() {
 | 
				
			||||||
 | 
					            var e = Array.prototype.slice.call(arguments, 0);
 | 
				
			||||||
 | 
					            return "load" === n && "string" == typeof e[0] ? Q.apply(this, e) : (r("jQuery.fn." + n + "() is deprecated"), 
 | 
				
			||||||
 | 
					            e.splice(0, 0, n), arguments.length ? this.on.apply(this, e) : (this.triggerHandler.apply(this, e), 
 | 
				
			||||||
 | 
					            this));
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }), e.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "), function(t, n) {
 | 
				
			||||||
 | 
					        e.fn[n] = function(e, t) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn." + n + "() event shorthand is deprecated"), arguments.length > 0 ? this.on(n, null, e, t) : this.trigger(n);
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					    }), e(function() {
 | 
				
			||||||
 | 
					        e(t.document).triggerHandler("ready");
 | 
				
			||||||
 | 
					    }), e.event.special.ready = {
 | 
				
			||||||
 | 
					        setup: function() {
 | 
				
			||||||
 | 
					            this === t.document && r("'ready' event is deprecated");
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }, e.fn.extend({
 | 
				
			||||||
 | 
					        bind: function(e, t, n) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn.bind() is deprecated"), this.on(e, null, t, n);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        unbind: function(e, t) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn.unbind() is deprecated"), this.off(e, null, t);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        delegate: function(e, t, n, a) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn.delegate() is deprecated"), this.on(t, e, n, a);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        undelegate: function(e, t, n) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn.undelegate() is deprecated"), 1 === arguments.length ? this.off(e, "**") : this.off(t, e || "**", n);
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
 | 
					        hover: function(e, t) {
 | 
				
			||||||
 | 
					            return r("jQuery.fn.hover() is deprecated"), this.on("mouseenter", e).on("mouseleave", t || e);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
 | 
					    var x = e.fn.offset;
 | 
				
			||||||
 | 
					    e.fn.offset = function() {
 | 
				
			||||||
 | 
					        var n, a = this[0], o = {
 | 
				
			||||||
 | 
					            top: 0,
 | 
				
			||||||
 | 
					            left: 0
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        return a && a.nodeType ? (n = (a.ownerDocument || t.document).documentElement, e.contains(n, a) ? x.apply(this, arguments) : (r("jQuery.fn.offset() requires an element connected to a document"), 
 | 
				
			||||||
 | 
					        o)) : (r("jQuery.fn.offset() requires a valid DOM element"), o);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var k = e.param;
 | 
				
			||||||
 | 
					    e.param = function(t, n) {
 | 
				
			||||||
 | 
					        var a = e.ajaxSettings && e.ajaxSettings.traditional;
 | 
				
			||||||
 | 
					        return void 0 === n && a && (r("jQuery.param() no longer uses jQuery.ajaxSettings.traditional"), 
 | 
				
			||||||
 | 
					        n = a), k.call(this, t, n);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var A = e.fn.andSelf || e.fn.addBack;
 | 
				
			||||||
 | 
					    e.fn.andSelf = function() {
 | 
				
			||||||
 | 
					        return r("jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()"), 
 | 
				
			||||||
 | 
					        A.apply(this, arguments);
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    var S = e.Deferred, q = [ [ "resolve", "done", e.Callbacks("once memory"), e.Callbacks("once memory"), "resolved" ], [ "reject", "fail", e.Callbacks("once memory"), e.Callbacks("once memory"), "rejected" ], [ "notify", "progress", e.Callbacks("memory"), e.Callbacks("memory") ] ];
 | 
				
			||||||
 | 
					    return e.Deferred = function(t) {
 | 
				
			||||||
 | 
					        var n = S(), a = n.promise();
 | 
				
			||||||
 | 
					        return n.pipe = a.pipe = function() {
 | 
				
			||||||
 | 
					            var t = arguments;
 | 
				
			||||||
 | 
					            return r("deferred.pipe() is deprecated"), e.Deferred(function(r) {
 | 
				
			||||||
 | 
					                e.each(q, function(o, i) {
 | 
				
			||||||
 | 
					                    var s = e.isFunction(t[o]) && t[o];
 | 
				
			||||||
 | 
					                    n[i[1]](function() {
 | 
				
			||||||
 | 
					                        var t = s && s.apply(this, arguments);
 | 
				
			||||||
 | 
					                        t && e.isFunction(t.promise) ? t.promise().done(r.resolve).fail(r.reject).progress(r.notify) : r[i[0] + "With"](this === a ? r.promise() : this, s ? [ t ] : arguments);
 | 
				
			||||||
 | 
					                    });
 | 
				
			||||||
 | 
					                }), t = null;
 | 
				
			||||||
 | 
					            }).promise();
 | 
				
			||||||
 | 
					        }, t && t.call(n, n), n;
 | 
				
			||||||
 | 
					    }, e.Deferred.exceptionHook = S.exceptionHook, e;
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
							
								
								
									
										7
									
								
								public/vendor/plugins/jquery/jquery.min.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								public/vendor/plugins/jquery/jquery.min.js
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							@@ -91,8 +91,7 @@ func CreateUser(ctx *context.APIContext, form api.CreateUserOption) {
 | 
				
			|||||||
	if form.SendNotify && setting.MailService != nil {
 | 
						if form.SendNotify && setting.MailService != nil {
 | 
				
			||||||
		models.SendRegisterNotifyMail(ctx.Context.Context, u)
 | 
							models.SendRegisterNotifyMail(ctx.Context.Context, u)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						ctx.JSON(201, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
 | 
				
			||||||
	ctx.JSON(201, u.APIFormat())
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// EditUser api for modifying a user's information
 | 
					// EditUser api for modifying a user's information
 | 
				
			||||||
@@ -181,7 +180,7 @@ func EditUser(ctx *context.APIContext, form api.EditUserOption) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
 | 
						log.Trace("Account profile updated by admin (%s): %s", ctx.User.Name, u.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(200, u.APIFormat())
 | 
						ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// DeleteUser api for deleting a user
 | 
					// DeleteUser api for deleting a user
 | 
				
			||||||
@@ -326,7 +325,7 @@ func GetAllUsers(ctx *context.APIContext) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	results := make([]*api.User, len(users))
 | 
						results := make([]*api.User, len(users))
 | 
				
			||||||
	for i := range users {
 | 
						for i := range users {
 | 
				
			||||||
		results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
							results[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.JSON(200, &results)
 | 
						ctx.JSON(200, &results)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -229,7 +229,7 @@ func ToTeam(team *models.Team) *api.Team {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ToUser convert models.User to api.User
 | 
					// ToUser convert models.User to api.User
 | 
				
			||||||
func ToUser(user *models.User, signed, admin bool) *api.User {
 | 
					func ToUser(user *models.User, signed, authed bool) *api.User {
 | 
				
			||||||
	result := &api.User{
 | 
						result := &api.User{
 | 
				
			||||||
		ID:        user.ID,
 | 
							ID:        user.ID,
 | 
				
			||||||
		UserName:  user.Name,
 | 
							UserName:  user.Name,
 | 
				
			||||||
@@ -239,7 +239,12 @@ func ToUser(user *models.User, signed, admin bool) *api.User {
 | 
				
			|||||||
		LastLogin: user.LastLoginUnix.AsTime(),
 | 
							LastLogin: user.LastLoginUnix.AsTime(),
 | 
				
			||||||
		Created:   user.CreatedUnix.AsTime(),
 | 
							Created:   user.CreatedUnix.AsTime(),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if signed && (!user.KeepEmailPrivate || admin) {
 | 
						// hide primary email if API caller isn't user itself or an admin
 | 
				
			||||||
 | 
						if !signed {
 | 
				
			||||||
 | 
							result.Email = ""
 | 
				
			||||||
 | 
						} else if user.KeepEmailPrivate && !authed {
 | 
				
			||||||
 | 
							result.Email = user.GetEmail()
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
		result.Email = user.Email
 | 
							result.Email = user.Email
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return result
 | 
						return result
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/api/v1/user"
 | 
						"code.gitea.io/gitea/routers/api/v1/user"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -46,7 +47,7 @@ func listMembers(ctx *context.APIContext, publicOnly bool) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	apiMembers := make([]*api.User, len(members))
 | 
						apiMembers := make([]*api.User, len(members))
 | 
				
			||||||
	for i, member := range members {
 | 
						for i, member := range members {
 | 
				
			||||||
		apiMembers[i] = member.APIFormat()
 | 
							apiMembers[i] = convert.ToUser(member, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, apiMembers)
 | 
						ctx.JSON(200, apiMembers)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -257,7 +257,7 @@ func GetTeamMembers(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	members := make([]*api.User, len(team.Members))
 | 
						members := make([]*api.User, len(team.Members))
 | 
				
			||||||
	for i, member := range team.Members {
 | 
						for i, member := range team.Members {
 | 
				
			||||||
		members[i] = member.APIFormat()
 | 
							members[i] = convert.ToUser(member, ctx.IsSigned, ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, members)
 | 
						ctx.JSON(200, members)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -288,7 +288,7 @@ func GetTeamMember(ctx *context.APIContext) {
 | 
				
			|||||||
	if ctx.Written() {
 | 
						if ctx.Written() {
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, u.APIFormat())
 | 
						ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.IsAdmin))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// AddTeamMember api for add a member to a team
 | 
					// AddTeamMember api for add a member to a team
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListCollaborators list a repository's collaborators
 | 
					// ListCollaborators list a repository's collaborators
 | 
				
			||||||
@@ -42,7 +43,7 @@ func ListCollaborators(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	users := make([]*api.User, len(collaborators))
 | 
						users := make([]*api.User, len(collaborators))
 | 
				
			||||||
	for i, collaborator := range collaborators {
 | 
						for i, collaborator := range collaborators {
 | 
				
			||||||
		users[i] = collaborator.APIFormat()
 | 
							users[i] = convert.ToUser(collaborator.User, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, users)
 | 
						ctx.JSON(200, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,7 +92,7 @@ func GetSingleCommit(ctx *context.APIContext) {
 | 
				
			|||||||
			URL: setting.AppURL + ctx.Link[1:],
 | 
								URL: setting.AppURL + ctx.Link[1:],
 | 
				
			||||||
			SHA: commit.ID.String(),
 | 
								SHA: commit.ID.String(),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		HTMLURL: ctx.Repo.Repository.HTMLURL() + "/commits/" + commit.ID.String(),
 | 
							HTMLURL: ctx.Repo.Repository.HTMLURL() + "/commit/" + commit.ID.String(),
 | 
				
			||||||
		RepoCommit: &api.RepoCommit{
 | 
							RepoCommit: &api.RepoCommit{
 | 
				
			||||||
			URL: setting.AppURL + ctx.Link[1:],
 | 
								URL: setting.AppURL + ctx.Link[1:],
 | 
				
			||||||
			Author: &api.CommitUser{
 | 
								Author: &api.CommitUser{
 | 
				
			||||||
@@ -111,7 +111,7 @@ func GetSingleCommit(ctx *context.APIContext) {
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
			Message: commit.Message(),
 | 
								Message: commit.Message(),
 | 
				
			||||||
			Tree: &api.CommitMeta{
 | 
								Tree: &api.CommitMeta{
 | 
				
			||||||
				URL: ctx.Repo.Repository.APIURL() + "/trees/" + commit.ID.String(),
 | 
									URL: ctx.Repo.Repository.APIURL() + "/git/trees/" + commit.ID.String(),
 | 
				
			||||||
				SHA: commit.ID.String(),
 | 
									SHA: commit.ID.String(),
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -130,8 +130,8 @@ func TestHook(ctx *context.APIContext) {
 | 
				
			|||||||
			convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
 | 
								convert.ToCommit(ctx.Repo.Repository, ctx.Repo.Commit),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		Repo:   ctx.Repo.Repository.APIFormat(models.AccessModeNone),
 | 
							Repo:   ctx.Repo.Repository.APIFormat(models.AccessModeNone),
 | 
				
			||||||
		Pusher: ctx.User.APIFormat(),
 | 
							Pusher: convert.ToUser(ctx.User, ctx.IsSigned, false),
 | 
				
			||||||
		Sender: ctx.User.APIFormat(),
 | 
							Sender: convert.ToUser(ctx.User, ctx.IsSigned, false),
 | 
				
			||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		ctx.Error(500, "PrepareWebhook: ", err)
 | 
							ctx.Error(500, "PrepareWebhook: ", err)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListStargazers list a repository's stargazers
 | 
					// ListStargazers list a repository's stargazers
 | 
				
			||||||
@@ -38,7 +39,7 @@ func ListStargazers(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	users := make([]*api.User, len(stargazers))
 | 
						users := make([]*api.User, len(stargazers))
 | 
				
			||||||
	for i, stargazer := range stargazers {
 | 
						for i, stargazer := range stargazers {
 | 
				
			||||||
		users[i] = stargazer.APIFormat()
 | 
							users[i] = convert.ToUser(stargazer, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, users)
 | 
						ctx.JSON(200, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,7 @@ import (
 | 
				
			|||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	api "code.gitea.io/gitea/modules/structs"
 | 
						api "code.gitea.io/gitea/modules/structs"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ListSubscribers list a repo's subscribers (i.e. watchers)
 | 
					// ListSubscribers list a repo's subscribers (i.e. watchers)
 | 
				
			||||||
@@ -38,7 +39,7 @@ func ListSubscribers(ctx *context.APIContext) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	users := make([]*api.User, len(subscribers))
 | 
						users := make([]*api.User, len(subscribers))
 | 
				
			||||||
	for i, subscriber := range subscribers {
 | 
						for i, subscriber := range subscribers {
 | 
				
			||||||
		users[i] = subscriber.APIFormat()
 | 
							users[i] = convert.ToUser(subscriber, ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, users)
 | 
						ctx.JSON(200, users)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,12 +9,13 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/context"
 | 
						"code.gitea.io/gitea/modules/context"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func responseAPIUsers(ctx *context.APIContext, users []*models.User) {
 | 
					func responseAPIUsers(ctx *context.APIContext, users []*models.User) {
 | 
				
			||||||
	apiUsers := make([]*api.User, len(users))
 | 
						apiUsers := make([]*api.User, len(users))
 | 
				
			||||||
	for i := range users {
 | 
						for i := range users {
 | 
				
			||||||
		apiUsers[i] = users[i].APIFormat()
 | 
							apiUsers[i] = convert.ToUser(users[i], ctx.IsSigned, ctx.User != nil && ctx.User.IsAdmin)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.JSON(200, &apiUsers)
 | 
						ctx.JSON(200, &apiUsers)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,13 +22,13 @@ func appendPrivateInformation(apiKey *api.PublicKey, key *models.PublicKey, defa
 | 
				
			|||||||
		apiKey.KeyType = "user"
 | 
							apiKey.KeyType = "user"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if defaultUser.ID == key.OwnerID {
 | 
							if defaultUser.ID == key.OwnerID {
 | 
				
			||||||
			apiKey.Owner = defaultUser.APIFormat()
 | 
								apiKey.Owner = convert.ToUser(defaultUser, true, true)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			user, err := models.GetUserByID(key.OwnerID)
 | 
								user, err := models.GetUserByID(key.OwnerID)
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				return apiKey, err
 | 
									return apiKey, err
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			apiKey.Owner = user.APIFormat()
 | 
								apiKey.Owner = convert.ToUser(user, true, true)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		apiKey.KeyType = "unknown"
 | 
							apiKey.KeyType = "unknown"
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -104,11 +104,7 @@ func GetInfo(ctx *context.APIContext) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Hide user e-mail when API caller isn't signed in.
 | 
						ctx.JSON(200, convert.ToUser(u, ctx.IsSigned, ctx.User.ID == u.ID || ctx.User.IsAdmin))
 | 
				
			||||||
	if !ctx.IsSigned {
 | 
					 | 
				
			||||||
		u.Email = ""
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	ctx.JSON(200, u.APIFormat())
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetAuthenticatedUser get current user's information
 | 
					// GetAuthenticatedUser get current user's information
 | 
				
			||||||
@@ -121,7 +117,7 @@ func GetAuthenticatedUser(ctx *context.APIContext) {
 | 
				
			|||||||
	// responses:
 | 
						// responses:
 | 
				
			||||||
	//   "200":
 | 
						//   "200":
 | 
				
			||||||
	//     "$ref": "#/responses/User"
 | 
						//     "$ref": "#/responses/User"
 | 
				
			||||||
	ctx.JSON(200, ctx.User.APIFormat())
 | 
						ctx.JSON(200, convert.ToUser(ctx.User, ctx.IsSigned, ctx.User != nil))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetUserHeatmapData is the handler to get a users heatmap
 | 
					// GetUserHeatmapData is the handler to get a users heatmap
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@ func Settings(ctx *context.Context) {
 | 
				
			|||||||
func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
 | 
					func SettingsPost(ctx *context.Context, form auth.UpdateOrgSettingForm) {
 | 
				
			||||||
	ctx.Data["Title"] = ctx.Tr("org.settings")
 | 
						ctx.Data["Title"] = ctx.Tr("org.settings")
 | 
				
			||||||
	ctx.Data["PageIsSettingsOptions"] = true
 | 
						ctx.Data["PageIsSettingsOptions"] = true
 | 
				
			||||||
 | 
						ctx.Data["CurrentVisibility"] = structs.VisibleType(ctx.Org.Organization.Visibility)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ctx.HasError() {
 | 
						if ctx.HasError() {
 | 
				
			||||||
		ctx.HTML(200, tplSettingsOptions)
 | 
							ctx.HTML(200, tplSettingsOptions)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -39,6 +39,7 @@ func Branches(ctx *context.Context) {
 | 
				
			|||||||
	ctx.Data["Title"] = "Branches"
 | 
						ctx.Data["Title"] = "Branches"
 | 
				
			||||||
	ctx.Data["IsRepoToolbarBranches"] = true
 | 
						ctx.Data["IsRepoToolbarBranches"] = true
 | 
				
			||||||
	ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
 | 
						ctx.Data["DefaultBranch"] = ctx.Repo.Repository.DefaultBranch
 | 
				
			||||||
 | 
						ctx.Data["AllowsPulls"] = ctx.Repo.Repository.AllowsPulls()
 | 
				
			||||||
	ctx.Data["IsWriter"] = ctx.Repo.CanWrite(models.UnitTypeCode)
 | 
						ctx.Data["IsWriter"] = ctx.Repo.CanWrite(models.UnitTypeCode)
 | 
				
			||||||
	ctx.Data["IsMirror"] = ctx.Repo.Repository.IsMirror
 | 
						ctx.Data["IsMirror"] = ctx.Repo.Repository.IsMirror
 | 
				
			||||||
	ctx.Data["PageIsViewCode"] = true
 | 
						ctx.Data["PageIsViewCode"] = true
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ import (
 | 
				
			|||||||
	"io/ioutil"
 | 
						"io/ioutil"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -137,7 +138,7 @@ func editFile(ctx *context.Context, isNewFile bool) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
							ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["new_branch_name"] = ""
 | 
						ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
 | 
				
			||||||
	ctx.Data["last_commit"] = ctx.Repo.CommitID
 | 
						ctx.Data["last_commit"] = ctx.Repo.CommitID
 | 
				
			||||||
	ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
 | 
						ctx.Data["MarkdownFileExts"] = strings.Join(setting.Markdown.FileExtensions, ",")
 | 
				
			||||||
	ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
 | 
						ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
 | 
				
			||||||
@@ -266,6 +267,10 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
 | 
				
			|||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, err), tplEditFile, &form)
 | 
								ctx.RenderWithErr(ctx.Tr("repo.editor.fail_to_update_file", form.TreePath, err), tplEditFile, &form)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if form.CommitChoice == frmCommitChoiceNewBranch {
 | 
				
			||||||
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@@ -335,7 +340,7 @@ func DeleteFile(ctx *context.Context) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
							ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["new_branch_name"] = ""
 | 
						ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.HTML(200, tplDeleteFile)
 | 
						ctx.HTML(200, tplDeleteFile)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -362,7 +367,7 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if branchName != ctx.Repo.BranchName && !canCommit {
 | 
						if branchName == ctx.Repo.BranchName && !canCommit {
 | 
				
			||||||
		ctx.Data["Err_NewBranchName"] = true
 | 
							ctx.Data["Err_NewBranchName"] = true
 | 
				
			||||||
		ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
							ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
				
			||||||
		ctx.RenderWithErr(ctx.Tr("repo.editor.cannot_commit_to_protected_branch", branchName), tplDeleteFile, &form)
 | 
							ctx.RenderWithErr(ctx.Tr("repo.editor.cannot_commit_to_protected_branch", branchName), tplDeleteFile, &form)
 | 
				
			||||||
@@ -387,20 +392,20 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
 | 
				
			|||||||
	}); err != nil {
 | 
						}); err != nil {
 | 
				
			||||||
		// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
 | 
							// This is where we handle all the errors thrown by repofiles.DeleteRepoFile
 | 
				
			||||||
		if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
 | 
							if git.IsErrNotExist(err) || models.IsErrRepoFileDoesNotExist(err) {
 | 
				
			||||||
			ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplEditFile, &form)
 | 
								ctx.RenderWithErr(ctx.Tr("repo.editor.file_deleting_no_longer_exists", ctx.Repo.TreePath), tplDeleteFile, &form)
 | 
				
			||||||
		} else if models.IsErrFilenameInvalid(err) {
 | 
							} else if models.IsErrFilenameInvalid(err) {
 | 
				
			||||||
			ctx.Data["Err_TreePath"] = true
 | 
								ctx.Data["Err_TreePath"] = true
 | 
				
			||||||
			ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplEditFile, &form)
 | 
								ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_invalid", ctx.Repo.TreePath), tplDeleteFile, &form)
 | 
				
			||||||
		} else if models.IsErrFilePathInvalid(err) {
 | 
							} else if models.IsErrFilePathInvalid(err) {
 | 
				
			||||||
			ctx.Data["Err_TreePath"] = true
 | 
								ctx.Data["Err_TreePath"] = true
 | 
				
			||||||
			if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
 | 
								if fileErr, ok := err.(models.ErrFilePathInvalid); ok {
 | 
				
			||||||
				switch fileErr.Type {
 | 
									switch fileErr.Type {
 | 
				
			||||||
				case git.EntryModeSymlink:
 | 
									case git.EntryModeSymlink:
 | 
				
			||||||
					ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplEditFile, &form)
 | 
										ctx.RenderWithErr(ctx.Tr("repo.editor.file_is_a_symlink", fileErr.Path), tplDeleteFile, &form)
 | 
				
			||||||
				case git.EntryModeTree:
 | 
									case git.EntryModeTree:
 | 
				
			||||||
					ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplEditFile, &form)
 | 
										ctx.RenderWithErr(ctx.Tr("repo.editor.filename_is_a_directory", fileErr.Path), tplDeleteFile, &form)
 | 
				
			||||||
				case git.EntryModeBlob:
 | 
									case git.EntryModeBlob:
 | 
				
			||||||
					ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplEditFile, &form)
 | 
										ctx.RenderWithErr(ctx.Tr("repo.editor.directory_is_a_file", fileErr.Path), tplDeleteFile, &form)
 | 
				
			||||||
				default:
 | 
									default:
 | 
				
			||||||
					ctx.ServerError("DeleteRepoFile", err)
 | 
										ctx.ServerError("DeleteRepoFile", err)
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -410,25 +415,44 @@ func DeleteFilePost(ctx *context.Context, form auth.DeleteRepoFileForm) {
 | 
				
			|||||||
		} else if git.IsErrBranchNotExist(err) {
 | 
							} else if git.IsErrBranchNotExist(err) {
 | 
				
			||||||
			// For when a user deletes a file to a branch that no longer exists
 | 
								// For when a user deletes a file to a branch that no longer exists
 | 
				
			||||||
			if branchErr, ok := err.(git.ErrBranchNotExist); ok {
 | 
								if branchErr, ok := err.(git.ErrBranchNotExist); ok {
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name), tplEditFile, &form)
 | 
									ctx.RenderWithErr(ctx.Tr("repo.editor.branch_does_not_exist", branchErr.Name), tplDeleteFile, &form)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				ctx.Error(500, err.Error())
 | 
									ctx.Error(500, err.Error())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if models.IsErrBranchAlreadyExists(err) {
 | 
							} else if models.IsErrBranchAlreadyExists(err) {
 | 
				
			||||||
			// For when a user specifies a new branch that already exists
 | 
								// For when a user specifies a new branch that already exists
 | 
				
			||||||
			if branchErr, ok := err.(models.ErrBranchAlreadyExists); ok {
 | 
								if branchErr, ok := err.(models.ErrBranchAlreadyExists); ok {
 | 
				
			||||||
				ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplEditFile, &form)
 | 
									ctx.RenderWithErr(ctx.Tr("repo.editor.branch_already_exists", branchErr.BranchName), tplDeleteFile, &form)
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				ctx.Error(500, err.Error())
 | 
									ctx.Error(500, err.Error())
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		} else if models.IsErrCommitIDDoesNotMatch(err) {
 | 
							} else if models.IsErrCommitIDDoesNotMatch(err) {
 | 
				
			||||||
			ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_editing", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplEditFile, &form)
 | 
								ctx.RenderWithErr(ctx.Tr("repo.editor.file_changed_while_deleting", ctx.Repo.RepoLink+"/compare/"+form.LastCommit+"..."+ctx.Repo.CommitID), tplDeleteFile, &form)
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			ctx.ServerError("DeleteRepoFile", err)
 | 
								ctx.ServerError("DeleteRepoFile", err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
 | 
				
			||||||
 | 
						if form.CommitChoice == frmCommitChoiceNewBranch {
 | 
				
			||||||
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ctx.Flash.Success(ctx.Tr("repo.editor.file_delete_success", ctx.Repo.TreePath))
 | 
							treePath := filepath.Dir(ctx.Repo.TreePath)
 | 
				
			||||||
		ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName))
 | 
							if treePath == "." {
 | 
				
			||||||
 | 
								treePath = "" // the file deleted was in the root, so we return the user to the root directory
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if len(treePath) > 0 {
 | 
				
			||||||
 | 
								// Need to get the latest commit since it changed
 | 
				
			||||||
 | 
								commit, err := ctx.Repo.GitRepo.GetBranchCommit(ctx.Repo.BranchName)
 | 
				
			||||||
 | 
								if err == nil && commit != nil {
 | 
				
			||||||
 | 
									// We have the comment, now find what directory we can return the user to
 | 
				
			||||||
 | 
									// (must have entries)
 | 
				
			||||||
 | 
									treePath = GetClosestParentWithFiles(treePath, commit)
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									treePath = "" // otherwise return them to the root of the repo
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(treePath))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -467,7 +491,7 @@ func UploadFile(ctx *context.Context) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
							ctx.Data["commit_choice"] = frmCommitChoiceNewBranch
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	ctx.Data["new_branch_name"] = ""
 | 
						ctx.Data["new_branch_name"] = GetUniquePatchBranchName(ctx)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.HTML(200, tplUploadFile)
 | 
						ctx.HTML(200, tplUploadFile)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -565,7 +589,11 @@ func UploadFilePost(ctx *context.Context, form auth.UploadRepoFileForm) {
 | 
				
			|||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
 | 
						if form.CommitChoice == frmCommitChoiceNewBranch {
 | 
				
			||||||
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/compare/" + ctx.Repo.BranchName + "..." + form.NewBranchName)
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(branchName) + "/" + util.PathEscapeSegments(form.TreePath))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func cleanUploadFileName(name string) string {
 | 
					func cleanUploadFileName(name string) string {
 | 
				
			||||||
@@ -645,3 +673,40 @@ func RemoveUploadFileFromServer(ctx *context.Context, form auth.RemoveUploadFile
 | 
				
			|||||||
	log.Trace("Upload file removed: %s", form.File)
 | 
						log.Trace("Upload file removed: %s", form.File)
 | 
				
			||||||
	ctx.Status(204)
 | 
						ctx.Status(204)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetUniquePatchBranchName Gets a unique branch name for a new patch branch
 | 
				
			||||||
 | 
					// It will be in the form of <username>-patch-<num> where <num> is the first branch of this format
 | 
				
			||||||
 | 
					// that doesn't already exist. If we exceed 1000 tries or an error is thrown, we just return "" so the user has to
 | 
				
			||||||
 | 
					// type in the branch name themselves (will be an empty field)
 | 
				
			||||||
 | 
					func GetUniquePatchBranchName(ctx *context.Context) string {
 | 
				
			||||||
 | 
						prefix := ctx.User.LowerName + "-patch-"
 | 
				
			||||||
 | 
						for i := 1; i <= 1000; i++ {
 | 
				
			||||||
 | 
							branchName := fmt.Sprintf("%s%d", prefix, i)
 | 
				
			||||||
 | 
							if _, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
 | 
				
			||||||
 | 
								if git.IsErrBranchNotExist(err) {
 | 
				
			||||||
 | 
									return branchName
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								log.Error("GetUniquePatchBranchName: %v", err)
 | 
				
			||||||
 | 
								return ""
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ""
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// GetClosestParentWithFiles Recursively gets the path of parent in a tree that has files (used when file in a tree is
 | 
				
			||||||
 | 
					// deleted). Returns "" for the root if no parents other than the root have files. If the given treePath isn't a
 | 
				
			||||||
 | 
					// SubTree or it has no entries, we go up one dir and see if we can return the user to that listing.
 | 
				
			||||||
 | 
					func GetClosestParentWithFiles(treePath string, commit *git.Commit) string {
 | 
				
			||||||
 | 
						if len(treePath) == 0 || treePath == "." {
 | 
				
			||||||
 | 
							return ""
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						// see if the tree has entries
 | 
				
			||||||
 | 
						if tree, err := commit.SubTree(treePath); err != nil {
 | 
				
			||||||
 | 
							// failed to get tree, going up a dir
 | 
				
			||||||
 | 
							return GetClosestParentWithFiles(filepath.Dir(treePath), commit)
 | 
				
			||||||
 | 
						} else if entries, err := tree.ListEntries(); err != nil || len(entries) == 0 {
 | 
				
			||||||
 | 
							// no files in this dir, going up a dir
 | 
				
			||||||
 | 
							return GetClosestParentWithFiles(filepath.Dir(treePath), commit)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return treePath
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,8 @@
 | 
				
			|||||||
package repo
 | 
					package repo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/git"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/test"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
@@ -37,3 +39,40 @@ func TestCleanUploadName(t *testing.T) {
 | 
				
			|||||||
		assert.EqualValues(t, cleanUploadFileName(k), v)
 | 
							assert.EqualValues(t, cleanUploadFileName(k), v)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetUniquePatchBranchName(t *testing.T) {
 | 
				
			||||||
 | 
						models.PrepareTestEnv(t)
 | 
				
			||||||
 | 
						ctx := test.MockContext(t, "user2/repo1")
 | 
				
			||||||
 | 
						ctx.SetParams(":id", "1")
 | 
				
			||||||
 | 
						test.LoadRepo(t, ctx, 1)
 | 
				
			||||||
 | 
						test.LoadRepoCommit(t, ctx)
 | 
				
			||||||
 | 
						test.LoadUser(t, ctx, 2)
 | 
				
			||||||
 | 
						test.LoadGitRepo(t, ctx)
 | 
				
			||||||
 | 
						expectedBranchName := "user2-patch-1"
 | 
				
			||||||
 | 
						branchName := GetUniquePatchBranchName(ctx)
 | 
				
			||||||
 | 
						assert.Equal(t, expectedBranchName, branchName)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestGetClosestParentWithFiles(t *testing.T) {
 | 
				
			||||||
 | 
						models.PrepareTestEnv(t)
 | 
				
			||||||
 | 
						ctx := test.MockContext(t, "user2/repo1")
 | 
				
			||||||
 | 
						ctx.SetParams(":id", "1")
 | 
				
			||||||
 | 
						test.LoadRepo(t, ctx, 1)
 | 
				
			||||||
 | 
						test.LoadRepoCommit(t, ctx)
 | 
				
			||||||
 | 
						test.LoadUser(t, ctx, 2)
 | 
				
			||||||
 | 
						test.LoadGitRepo(t, ctx)
 | 
				
			||||||
 | 
						repo := ctx.Repo.Repository
 | 
				
			||||||
 | 
						branch := repo.DefaultBranch
 | 
				
			||||||
 | 
						gitRepo, _ := git.OpenRepository(repo.RepoPath())
 | 
				
			||||||
 | 
						commit, _ := gitRepo.GetBranchCommit(branch)
 | 
				
			||||||
 | 
						expectedTreePath := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						expectedTreePath = "" // Should return the root dir, empty string, since there are no subdirs in this repo
 | 
				
			||||||
 | 
						for _, deletedFile := range []string{
 | 
				
			||||||
 | 
							"dir1/dir2/dir3/file.txt",
 | 
				
			||||||
 | 
							"file.txt",
 | 
				
			||||||
 | 
						} {
 | 
				
			||||||
 | 
							treePath := GetClosestParentWithFiles(deletedFile, commit)
 | 
				
			||||||
 | 
							assert.Equal(t, expectedTreePath, treePath)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -215,7 +215,10 @@ func HTTP(ctx *context.Context) {
 | 
				
			|||||||
				// Check username and password
 | 
									// Check username and password
 | 
				
			||||||
				authUser, err = models.UserSignIn(authUsername, authPasswd)
 | 
									authUser, err = models.UserSignIn(authUsername, authPasswd)
 | 
				
			||||||
				if err != nil {
 | 
									if err != nil {
 | 
				
			||||||
					if !models.IsErrUserNotExist(err) {
 | 
										if models.IsErrUserProhibitLogin(err) {
 | 
				
			||||||
 | 
											ctx.HandleText(http.StatusForbidden, "User is not permitted to login")
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										} else if !models.IsErrUserNotExist(err) {
 | 
				
			||||||
						ctx.ServerError("UserSignIn error: %v", err)
 | 
											ctx.ServerError("UserSignIn error: %v", err)
 | 
				
			||||||
						return
 | 
											return
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -665,7 +665,7 @@ func RegisterRoutes(m *macaron.Macaron) {
 | 
				
			|||||||
		}, func(ctx *context.Context) {
 | 
							}, func(ctx *context.Context) {
 | 
				
			||||||
			ctx.Data["PageIsSettings"] = true
 | 
								ctx.Data["PageIsSettings"] = true
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}, reqSignIn, context.RepoAssignment(), reqRepoAdmin, context.UnitTypes(), context.RepoRef())
 | 
						}, reqSignIn, context.RepoAssignment(), context.UnitTypes(), reqRepoAdmin, context.RepoRef())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
 | 
						m.Get("/:username/:reponame/action/:action", reqSignIn, context.RepoAssignment(), context.UnitTypes(), repo.Action)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	{{template "base/footer_content" .}}
 | 
						{{template "base/footer_content" .}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js"></script>
 | 
						<script src="{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1"></script>
 | 
				
			||||||
 | 
						<script src="{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1"></script>
 | 
				
			||||||
	<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
 | 
						<script src="{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js"></script>
 | 
				
			||||||
{{if .RequireSimpleMDE}}
 | 
					{{if .RequireSimpleMDE}}
 | 
				
			||||||
	<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script>
 | 
						<script src="{{AppSubUrl}}/vendor/plugins/simplemde/simplemde.min.js"></script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,23 +17,19 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
 | 
										<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
 | 
				
			||||||
						<span class="inline required field"><label for="visibility">{{.i18n.Tr "org.settings.visibility"}}</label></span>
 | 
											<span class="inline required field"><label for="visibility">{{.i18n.Tr "org.settings.visibility"}}</label></span>
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
											<div class="inline-grouped-list">
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="0" {{if .DefaultOrgVisibilityMode.IsPublic}}checked{{end}}/>
 | 
												<div class="ui radio checkbox">
 | 
				
			||||||
							<label>{{.i18n.Tr "org.settings.visibility.public"}}</label>
 | 
													<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="0" {{if .DefaultOrgVisibilityMode.IsPublic}}checked{{end}}/>
 | 
				
			||||||
						</div>
 | 
													<label>{{.i18n.Tr "org.settings.visibility.public"}}</label>
 | 
				
			||||||
					</div>
 | 
												</div>
 | 
				
			||||||
					<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
 | 
												<div class="ui radio checkbox">
 | 
				
			||||||
						<label> </label>
 | 
													<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="1" {{if .DefaultOrgVisibilityMode.IsLimited}}checked{{end}}/>
 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
													<label>{{.i18n.Tr "org.settings.visibility.limited"}}</label>
 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="1" {{if .DefaultOrgVisibilityMode.IsLimited}}checked{{end}}/>
 | 
												</div>
 | 
				
			||||||
							<label>{{.i18n.Tr "org.settings.visibility.limited"}}</label>
 | 
												<div class="ui radio checkbox">
 | 
				
			||||||
						</div>
 | 
													<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="2" {{if .DefaultOrgVisibilityMode.IsPrivate}}checked{{end}}/>
 | 
				
			||||||
					</div>
 | 
													<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
 | 
				
			||||||
					<div class="inline field {{if .Err_OrgVisibility}}error{{end}}">
 | 
												</div>
 | 
				
			||||||
						<label> </label>
 | 
					 | 
				
			||||||
						<div class="ui radio checkbox">
 | 
					 | 
				
			||||||
							<input class="hidden enable-system-radio" tabindex="0" name="visibility" type="radio" value="2" {{if .DefaultOrgVisibilityMode.IsPrivate}}checked{{end}}/>
 | 
					 | 
				
			||||||
							<label>{{.i18n.Tr "org.settings.visibility.private"}}</label>
 | 
					 | 
				
			||||||
						</div>
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
					<div class="inline field">
 | 
										<div class="inline field">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,8 @@ var STATIC_CACHE = 'static-cache-v1';
 | 
				
			|||||||
var urlsToCache = [
 | 
					var urlsToCache = [
 | 
				
			||||||
  // js
 | 
					  // js
 | 
				
			||||||
  '{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js',
 | 
					  '{{AppSubUrl}}/vendor/plugins/jquery.areyousure/jquery.are-you-sure.js',
 | 
				
			||||||
  '{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js',
 | 
					  '{{AppSubUrl}}/vendor/plugins/jquery/jquery.min.js?v=3.4.1',
 | 
				
			||||||
 | 
					  '{{AppSubUrl}}/vendor/plugins/jquery-migrate/jquery-migrate.min.js?v=3.0.1',
 | 
				
			||||||
  '{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js',
 | 
					  '{{AppSubUrl}}/vendor/plugins/semantic/semantic.min.js',
 | 
				
			||||||
  '{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}',
 | 
					  '{{AppSubUrl}}/js/index.js?v={{MD5 AppVer}}',
 | 
				
			||||||
  '{{AppSubUrl}}/js/draw.js',
 | 
					  '{{AppSubUrl}}/js/draw.js',
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,11 +2,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	<h4 class="ui top attached header" id="repo-read-file">
 | 
						<h4 class="ui top attached header" id="repo-read-file">
 | 
				
			||||||
		<div class="ui stackable grid">
 | 
							<div class="ui stackable grid">
 | 
				
			||||||
			<div class="ten wide column">
 | 
								<div class="eight wide column">
 | 
				
			||||||
                <i class="file text outline icon ui left"></i>
 | 
					                <i class="file text outline icon ui left"></i>
 | 
				
			||||||
                <strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
 | 
					                <strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="six wide right aligned column">
 | 
								<div class="eight wide right aligned column">
 | 
				
			||||||
                <div class="ui right file-actions">
 | 
					                <div class="ui right file-actions">
 | 
				
			||||||
                    <div class="ui buttons">
 | 
					                    <div class="ui buttons">
 | 
				
			||||||
                        {{if not .IsViewCommit}}
 | 
					                        {{if not .IsViewCommit}}
 | 
				
			||||||
@@ -48,4 +48,4 @@
 | 
				
			|||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,16 @@
 | 
				
			|||||||
			<table class="ui very basic striped fixed table single line">
 | 
								<table class="ui very basic striped fixed table single line">
 | 
				
			||||||
				<tbody>
 | 
									<tbody>
 | 
				
			||||||
					<tr>
 | 
										<tr>
 | 
				
			||||||
						<td>{{.DefaultBranch}}</td>
 | 
											<td>
 | 
				
			||||||
 | 
												{{range .Branches}}
 | 
				
			||||||
 | 
													{{if eq .Name $.DefaultBranch}}
 | 
				
			||||||
 | 
														{{if .IsProtected}}
 | 
				
			||||||
 | 
															<i class="octicon octicon-shield"></i>
 | 
				
			||||||
 | 
														{{end}}
 | 
				
			||||||
 | 
														{{.Name}}
 | 
				
			||||||
 | 
													{{end}}
 | 
				
			||||||
 | 
												{{end}}
 | 
				
			||||||
 | 
											</td>
 | 
				
			||||||
					</tr>
 | 
										</tr>
 | 
				
			||||||
				</tbody>
 | 
									</tbody>
 | 
				
			||||||
			</table>
 | 
								</table>
 | 
				
			||||||
@@ -27,15 +36,15 @@
 | 
				
			|||||||
					<thead>
 | 
										<thead>
 | 
				
			||||||
						<tr>
 | 
											<tr>
 | 
				
			||||||
							<th class="six wide">{{.i18n.Tr "repo.branch.name"}}</th>
 | 
												<th class="six wide">{{.i18n.Tr "repo.branch.name"}}</th>
 | 
				
			||||||
 | 
												<th class="three wide"></th>
 | 
				
			||||||
							<th class="two wide"></th>
 | 
												<th class="two wide"></th>
 | 
				
			||||||
							<th class="two wide"></th>
 | 
												{{if and $.IsWriter (not $.IsMirror) (not $.Repository.IsArchived)}}
 | 
				
			||||||
							{{if and $.IsWriter (not $.IsMirror)}}
 | 
					 | 
				
			||||||
								<th class="one wide right aligned">{{.i18n.Tr "repo.branch.delete_head"}}</th>
 | 
													<th class="one wide right aligned">{{.i18n.Tr "repo.branch.delete_head"}}</th>
 | 
				
			||||||
							{{end}}
 | 
												{{end}}
 | 
				
			||||||
						</tr>
 | 
											</tr>
 | 
				
			||||||
					</thead>
 | 
										</thead>
 | 
				
			||||||
					<tbody>
 | 
										<tbody>
 | 
				
			||||||
						{{range $branch := .Branches}}
 | 
											{{range .Branches}}
 | 
				
			||||||
							{{if ne .Name $.DefaultBranch}}
 | 
												{{if ne .Name $.DefaultBranch}}
 | 
				
			||||||
								<tr>
 | 
													<tr>
 | 
				
			||||||
									<td>
 | 
														<td>
 | 
				
			||||||
@@ -43,6 +52,9 @@
 | 
				
			|||||||
										<s><a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a></s>
 | 
															<s><a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a></s>
 | 
				
			||||||
										<p class="time">{{$.i18n.Tr "repo.branch.deleted_by" .DeletedBranch.DeletedBy.Name}} {{TimeSinceUnix .DeletedBranch.DeletedUnix $.i18n.Lang}}</p>
 | 
															<p class="time">{{$.i18n.Tr "repo.branch.deleted_by" .DeletedBranch.DeletedBy.Name}} {{TimeSinceUnix .DeletedBranch.DeletedUnix $.i18n.Lang}}</p>
 | 
				
			||||||
									{{else}}
 | 
														{{else}}
 | 
				
			||||||
 | 
															{{if .IsProtected}}
 | 
				
			||||||
 | 
																<i class="octicon octicon-shield"></i>
 | 
				
			||||||
 | 
															{{end}}
 | 
				
			||||||
										<a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a>
 | 
															<a href="{{$.RepoLink}}/src/branch/{{.Name | EscapePound}}">{{.Name}}</a>
 | 
				
			||||||
										<p class="time">{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
 | 
															<p class="time">{{$.i18n.Tr "org.repo_updated"}} {{TimeSince .Commit.Committer.When $.i18n.Lang}}</p>
 | 
				
			||||||
									{{end}}
 | 
														{{end}}
 | 
				
			||||||
@@ -63,7 +75,7 @@
 | 
				
			|||||||
									</td>
 | 
														</td>
 | 
				
			||||||
									<td class="right aligned">
 | 
														<td class="right aligned">
 | 
				
			||||||
										{{if not .LatestPullRequest}}
 | 
															{{if not .LatestPullRequest}}
 | 
				
			||||||
											{{if not .IsDeleted}}
 | 
																{{if and (not .IsDeleted) $.AllowsPulls}}
 | 
				
			||||||
											<a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
 | 
																<a href="{{$.RepoLink}}/compare/{{$.DefaultBranch | EscapePound}}...{{if ne $.Repository.Owner.Name $.Owner.Name}}{{$.Owner.Name}}:{{end}}{{.Name | EscapePound}}">
 | 
				
			||||||
												<button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
 | 
																	<button id="new-pull-request" class="ui compact basic button">{{$.i18n.Tr "repo.pulls.compare_changes"}}</button>
 | 
				
			||||||
											</a>
 | 
																</a>
 | 
				
			||||||
@@ -79,13 +91,11 @@
 | 
				
			|||||||
											{{end}}
 | 
																{{end}}
 | 
				
			||||||
										{{end}}
 | 
															{{end}}
 | 
				
			||||||
									</td>
 | 
														</td>
 | 
				
			||||||
									{{if and $.IsWriter (not $.IsMirror)}}
 | 
														{{if and $.IsWriter (not $.IsMirror) (not $.Repository.IsArchived)}}
 | 
				
			||||||
										<td class="right aligned">
 | 
															<td class="right aligned">
 | 
				
			||||||
										{{if .IsProtected}}
 | 
															{{if and .IsDeleted (not .IsProtected)}}
 | 
				
			||||||
											<i class="octicon octicon-shield"></i>
 | 
					 | 
				
			||||||
										{{else if .IsDeleted}}
 | 
					 | 
				
			||||||
											<a class="undo-button" href data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID | urlquery}}&name={{.DeletedBranch.Name | urlquery}}"><i class="octicon octicon-reply"></i></a>
 | 
																<a class="undo-button" href data-url="{{$.Link}}/restore?branch_id={{.DeletedBranch.ID | urlquery}}&name={{.DeletedBranch.Name | urlquery}}"><i class="octicon octicon-reply"></i></a>
 | 
				
			||||||
										{{else}}
 | 
															{{else if (not .IsProtected)}}
 | 
				
			||||||
											<a class="delete-branch-button" href data-url="{{$.Link}}/delete?name={{.Name | urlquery}}" data-name="{{.Name}}"><i class="trash icon text red"></i></a>
 | 
																<a class="delete-branch-button" href data-url="{{$.Link}}/delete?name={{.Name | urlquery}}" data-name="{{.Name}}"><i class="trash icon text red"></i></a>
 | 
				
			||||||
										{{end}}
 | 
															{{end}}
 | 
				
			||||||
										</td>
 | 
															</td>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -122,10 +122,10 @@
 | 
				
			|||||||
													<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
 | 
																		<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
 | 
				
			||||||
														<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
 | 
																			<td class="lines-num lines-num-old" data-line-num="{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}"><span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}"></span></td>
 | 
				
			||||||
														<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
 | 
																			<td class="lines-type-marker lines-type-marker-old">{{if $line.LeftIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
 | 
				
			||||||
														<td class="lines-code lines-code-old halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui green button add-code-comment add-code-comment-left" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
 | 
																			<td class="lines-code lines-code-old halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 2))}}<a class="ui green button add-code-comment add-code-comment-left" data-path="{{$file.Name}}" data-side="left" data-idx="{{$line.LeftIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.LeftIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
 | 
				
			||||||
														<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
 | 
																			<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
 | 
				
			||||||
														<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
 | 
																			<td class="lines-type-marker lines-type-marker-new">{{if $line.RightIdx}}<span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span>{{end}}</td>
 | 
				
			||||||
														<td class="lines-code lines-code-new halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui green button add-code-comment add-code-comment-right" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
 | 
																			<td class="lines-code lines-code-new halfwidth">{{if and $.SignedUserID $line.CanComment $.PageIsPullFiles (not (eq .GetType 3))}}<a class="ui green button add-code-comment add-code-comment-right" data-path="{{$file.Name}}" data-side="right" data-idx="{{$line.RightIdx}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{if $line.RightIdx}}{{$section.GetComputedInlineDiffFor $line}}{{end}}</span></td>
 | 
				
			||||||
													</tr>
 | 
																		</tr>
 | 
				
			||||||
													{{if gt (len $line.Comments) 0}}
 | 
																		{{if gt (len $line.Comments) 0}}
 | 
				
			||||||
														<tr class="add-code-comment">
 | 
																			<tr class="add-code-comment">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,7 +12,7 @@
 | 
				
			|||||||
			<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
 | 
								<td class="lines-num lines-num-new" data-line-num="{{if $line.RightIdx}}{{$line.RightIdx}}{{end}}"><span rel="{{if $line.RightIdx}}diff-{{Sha1 $file.Name}}R{{$line.RightIdx}}{{end}}"></span></td>
 | 
				
			||||||
			{{end}}
 | 
								{{end}}
 | 
				
			||||||
			<td class="lines-type-marker"><span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
 | 
								<td class="lines-type-marker"><span class="mono" data-type-marker="{{$line.GetLineTypeMarker}}"></span></td>
 | 
				
			||||||
			<td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles}}<a class="ui green button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}" data-path="{{$file.Name}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}}nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</span></td>
 | 
								<td class="lines-code{{if (not $line.RightIdx)}} lines-code-old{{end}}">{{if and $.root.SignedUserID $line.CanComment $.root.PageIsPullFiles}}<a class="ui green button add-code-comment add-code-comment-{{if $line.RightIdx}}right{{else}}left{{end}}" data-path="{{$file.Name}}" data-side="{{if $line.RightIdx}}right{{else}}left{{end}}" data-idx="{{if $line.RightIdx}}{{$line.RightIdx}}{{else}}{{$line.LeftIdx}}{{end}}">+</a>{{end}}<span class="mono wrap{{if $highlightClass}} language-{{$highlightClass}}{{else}} nohighlight{{end}}">{{$section.GetComputedInlineDiffFor $line}}</span></td>
 | 
				
			||||||
		</tr>
 | 
							</tr>
 | 
				
			||||||
		{{if gt (len $line.Comments) 0}}
 | 
							{{if gt (len $line.Comments) 0}}
 | 
				
			||||||
		<tr>
 | 
							<tr>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
		<div class="quick-pull-choice js-quick-pull-choice">
 | 
							<div class="quick-pull-choice js-quick-pull-choice">
 | 
				
			||||||
			<div class="field">
 | 
								<div class="field">
 | 
				
			||||||
		 		<div class="ui radio checkbox {{if not .CanCommitToBranch}}disabled{{end}}">
 | 
							 		<div class="ui radio checkbox {{if not .CanCommitToBranch}}disabled{{end}}">
 | 
				
			||||||
					<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct" {{if eq .commit_choice "direct"}}checked{{end}}>
 | 
										<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="direct" button_text="{{.i18n.Tr "repo.editor.commit_changes"}}" {{if eq .commit_choice "direct"}}checked{{end}}>
 | 
				
			||||||
					<label>
 | 
										<label>
 | 
				
			||||||
						<i class="octicon octicon-git-commit" height="16" width="14"></i>
 | 
											<i class="octicon octicon-git-commit" height="16" width="14"></i>
 | 
				
			||||||
						{{.i18n.Tr "repo.editor.commit_directly_to_this_branch" (.BranchName|Escape) | Safe}}
 | 
											{{.i18n.Tr "repo.editor.commit_directly_to_this_branch" (.BranchName|Escape) | Safe}}
 | 
				
			||||||
@@ -20,7 +20,7 @@
 | 
				
			|||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="field">
 | 
								<div class="field">
 | 
				
			||||||
				<div class="ui radio checkbox">
 | 
									<div class="ui radio checkbox">
 | 
				
			||||||
					<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
 | 
										<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{.i18n.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
 | 
				
			||||||
					<label>
 | 
										<label>
 | 
				
			||||||
						<i class="octicon octicon-git-pull-request" height="16" width="12"></i>
 | 
											<i class="octicon octicon-git-pull-request" height="16" width="12"></i>
 | 
				
			||||||
						{{.i18n.Tr "repo.editor.create_new_branch" | Safe}}
 | 
											{{.i18n.Tr "repo.editor.create_new_branch" | Safe}}
 | 
				
			||||||
@@ -36,8 +36,8 @@
 | 
				
			|||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<button type="submit" class="ui green button">
 | 
						<button id="commit-button" type="submit" class="ui green button">
 | 
				
			||||||
		{{.i18n.Tr "repo.editor.commit_changes"}}
 | 
							{{if eq .commit_choice "commit-to-new-branch"}}{{.i18n.Tr "repo.editor.propose_file_change"}}{{else}}{{.i18n.Tr "repo.editor.commit_changes"}}{{end}}
 | 
				
			||||||
	</button>
 | 
						</button>
 | 
				
			||||||
	<a class="ui button red" href="{{EscapePound $.BranchLink}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.editor.cancel"}}</a>
 | 
						<a class="ui button red" href="{{EscapePound $.BranchLink}}/{{EscapePound .TreePath}}">{{.i18n.Tr "repo.editor.cancel"}}</a>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
<div class="{{TabSizeClass .Editorconfig .FileName}} non-diff-file-content">
 | 
					<div class="{{TabSizeClass .Editorconfig .FileName}} non-diff-file-content">
 | 
				
			||||||
	<h4 class="ui top attached header" id="{{if .ReadmeExist}}repo-readme{{else}}repo-read-file{{end}}">
 | 
						<h4 class="ui top attached header" id="{{if .ReadmeExist}}repo-readme{{else}}repo-read-file{{end}}">
 | 
				
			||||||
		<div class="ui stackable grid">
 | 
							<div class="ui stackable grid">
 | 
				
			||||||
			<div class="ten wide column">
 | 
								<div class="eight wide column">
 | 
				
			||||||
				{{if .ReadmeExist}}
 | 
									{{if .ReadmeExist}}
 | 
				
			||||||
					<i class="book icon ui left"></i>
 | 
										<i class="book icon ui left"></i>
 | 
				
			||||||
					{{if .ReadmeInList}}
 | 
										{{if .ReadmeInList}}
 | 
				
			||||||
@@ -14,7 +14,7 @@
 | 
				
			|||||||
					<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
 | 
										<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}{{if .IsLFSFile}} ({{.i18n.Tr "repo.stored_lfs"}}){{end}}</span>
 | 
				
			||||||
				{{end}}
 | 
									{{end}}
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="six wide right aligned column">
 | 
								<div class="eight wide right aligned column">
 | 
				
			||||||
				{{if not .ReadmeInList}}
 | 
									{{if not .ReadmeInList}}
 | 
				
			||||||
					<div class="ui right file-actions">
 | 
										<div class="ui right file-actions">
 | 
				
			||||||
						<div class="ui buttons">
 | 
											<div class="ui buttons">
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								vendor/github.com/go-macaron/captcha/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/go-macaron/captcha/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,14 +1,10 @@
 | 
				
			|||||||
sudo: false
 | 
					sudo: false
 | 
				
			||||||
language: go
 | 
					language: go
 | 
				
			||||||
 | 
					 | 
				
			||||||
go:
 | 
					go:
 | 
				
			||||||
  - 1.3
 | 
					  - 1.6.x
 | 
				
			||||||
  - 1.4
 | 
					  - 1.7.x
 | 
				
			||||||
  - 1.5
 | 
					  - 1.8.x
 | 
				
			||||||
  - tip
 | 
					  - 1.9.x
 | 
				
			||||||
 | 
					  - 1.10.x
 | 
				
			||||||
 | 
					
 | 
				
			||||||
script: go test -v -cover -race
 | 
					script: go test -v -cover -race
 | 
				
			||||||
 | 
					 | 
				
			||||||
notifications:
 | 
					 | 
				
			||||||
  email:
 | 
					 | 
				
			||||||
    - u@gogs.io
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										26
									
								
								vendor/github.com/go-macaron/captcha/captcha.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/go-macaron/captcha/captcha.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -19,6 +19,7 @@ package captcha
 | 
				
			|||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"html/template"
 | 
						"html/template"
 | 
				
			||||||
 | 
						"image/color"
 | 
				
			||||||
	"path"
 | 
						"path"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -49,6 +50,7 @@ type Captcha struct {
 | 
				
			|||||||
	ChallengeNums    int
 | 
						ChallengeNums    int
 | 
				
			||||||
	Expiration       int64
 | 
						Expiration       int64
 | 
				
			||||||
	CachePrefix      string
 | 
						CachePrefix      string
 | 
				
			||||||
 | 
						ColorPalette     color.Palette
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// generate key string
 | 
					// generate key string
 | 
				
			||||||
@@ -61,16 +63,21 @@ func (c *Captcha) genRandChars() string {
 | 
				
			|||||||
	return string(com.RandomCreateBytes(c.ChallengeNums, defaultChars...))
 | 
						return string(com.RandomCreateBytes(c.ChallengeNums, defaultChars...))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// tempalte func for output html
 | 
					// CreateHTML outputs HTML for display and fetch new captcha images.
 | 
				
			||||||
func (c *Captcha) CreateHtml() template.HTML {
 | 
					func (c *Captcha) CreateHTML() template.HTML {
 | 
				
			||||||
	value, err := c.CreateCaptcha()
 | 
						value, err := c.CreateCaptcha()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		panic(fmt.Errorf("fail to create captcha: %v", err))
 | 
							panic(fmt.Errorf("fail to create captcha: %v", err))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return template.HTML(fmt.Sprintf(`<input type="hidden" name="%s" value="%s">
 | 
						return template.HTML(fmt.Sprintf(`<input type="hidden" name="%[1]s" value="%[2]s">
 | 
				
			||||||
	<a class="captcha" href="javascript:">
 | 
						<a class="captcha" href="javascript:" tabindex="-1">
 | 
				
			||||||
		<img onclick="this.src=('%s%s%s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%s%s%s.png">
 | 
							<img onclick="this.src=('%[3]s%[4]s%[2]s.png?reload='+(new Date()).getTime())" class="captcha-img" src="%[3]s%[4]s%[2]s.png">
 | 
				
			||||||
	</a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix, value, c.SubURL, c.URLPrefix, value))
 | 
						</a>`, c.FieldIdName, value, c.SubURL, c.URLPrefix))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DEPRECATED
 | 
				
			||||||
 | 
					func (c *Captcha) CreateHtml() template.HTML {
 | 
				
			||||||
 | 
						return c.CreateHTML()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// create a new captcha id
 | 
					// create a new captcha id
 | 
				
			||||||
@@ -139,6 +146,9 @@ type Options struct {
 | 
				
			|||||||
	Expiration int64
 | 
						Expiration int64
 | 
				
			||||||
	// Cache key prefix captcha characters. Default is "captcha_".
 | 
						// Cache key prefix captcha characters. Default is "captcha_".
 | 
				
			||||||
	CachePrefix string
 | 
						CachePrefix string
 | 
				
			||||||
 | 
						// ColorPalette holds a collection of primary colors used for
 | 
				
			||||||
 | 
						// the captcha's text. If not defined, a random color will be generated.
 | 
				
			||||||
 | 
						ColorPalette color.Palette
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func prepareOptions(options []Options) Options {
 | 
					func prepareOptions(options []Options) Options {
 | 
				
			||||||
@@ -192,6 +202,7 @@ func NewCaptcha(opt Options) *Captcha {
 | 
				
			|||||||
		ChallengeNums:    opt.ChallengeNums,
 | 
							ChallengeNums:    opt.ChallengeNums,
 | 
				
			||||||
		Expiration:       opt.Expiration,
 | 
							Expiration:       opt.Expiration,
 | 
				
			||||||
		CachePrefix:      opt.CachePrefix,
 | 
							CachePrefix:      opt.CachePrefix,
 | 
				
			||||||
 | 
							ColorPalette:     opt.ColorPalette,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -229,9 +240,10 @@ func Captchaer(options ...Options) macaron.Handler {
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if _, err := NewImage([]byte(chars), cpt.StdWidth, cpt.StdHeight).WriteTo(ctx.Resp); err != nil {
 | 
								if _, err := NewImage([]byte(chars), cpt.StdWidth, cpt.StdHeight, cpt.ColorPalette).WriteTo(ctx.Resp); err != nil {
 | 
				
			||||||
				panic(fmt.Errorf("write captcha: %v", err))
 | 
									panic(fmt.Errorf("write captcha: %v", err))
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								ctx.Status(200)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										25
									
								
								vendor/github.com/go-macaron/captcha/image.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										25
									
								
								vendor/github.com/go-macaron/captcha/image.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -265,16 +265,22 @@ func randFloat(from, to float64) float64 {
 | 
				
			|||||||
	return (to-from)*prng.Float64() + from
 | 
						return (to-from)*prng.Float64() + from
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func randomPalette() color.Palette {
 | 
					func randomPalette(primary color.Palette) color.Palette {
 | 
				
			||||||
	p := make([]color.Color, circleCount+1)
 | 
						p := make([]color.Color, circleCount+1)
 | 
				
			||||||
	// Transparent color.
 | 
						// Transparent color.
 | 
				
			||||||
	p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
 | 
						p[0] = color.RGBA{0xFF, 0xFF, 0xFF, 0x00}
 | 
				
			||||||
	// Primary color.
 | 
						// Primary color.
 | 
				
			||||||
	prim := color.RGBA{
 | 
						var prim color.RGBA
 | 
				
			||||||
		uint8(randIntn(129)),
 | 
						if len(primary) == 0 {
 | 
				
			||||||
		uint8(randIntn(129)),
 | 
							prim = color.RGBA{
 | 
				
			||||||
		uint8(randIntn(129)),
 | 
								uint8(randIntn(129)),
 | 
				
			||||||
		0xFF,
 | 
								uint8(randIntn(129)),
 | 
				
			||||||
 | 
								uint8(randIntn(129)),
 | 
				
			||||||
 | 
								0xFF,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							r, g, b, a := primary[randIntn(len(primary)-1)].RGBA()
 | 
				
			||||||
 | 
							prim = color.RGBA{uint8(r), uint8(g), uint8(b), uint8(a)}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	p[1] = prim
 | 
						p[1] = prim
 | 
				
			||||||
	// Circle colors.
 | 
						// Circle colors.
 | 
				
			||||||
@@ -285,10 +291,11 @@ func randomPalette() color.Palette {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewImage returns a new captcha image of the given width and height with the
 | 
					// NewImage returns a new captcha image of the given width and height with the
 | 
				
			||||||
// given digits, where each digit must be in range 0-9.
 | 
					// given digits, where each digit must be in range 0-9. The digit's color is
 | 
				
			||||||
func NewImage(digits []byte, width, height int) *Image {
 | 
					// chosen by random from the colorPalette.
 | 
				
			||||||
 | 
					func NewImage(digits []byte, width, height int, colorPalette color.Palette) *Image {
 | 
				
			||||||
	m := new(Image)
 | 
						m := new(Image)
 | 
				
			||||||
	m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette())
 | 
						m.Paletted = image.NewPaletted(image.Rect(0, 0, width, height), randomPalette(colorPalette))
 | 
				
			||||||
	m.calculateSizes(width, height, len(digits))
 | 
						m.calculateSizes(width, height, len(digits))
 | 
				
			||||||
	// Randomly position captcha inside the image.
 | 
						// Randomly position captcha inside the image.
 | 
				
			||||||
	maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
 | 
						maxx := width - (m.numWidth+m.dotSize)*len(digits) - m.dotSize
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/modules.txt
									
									
									
									
										vendored
									
									
								
							@@ -85,7 +85,7 @@ github.com/couchbase/vellum/utf8
 | 
				
			|||||||
github.com/couchbaselabs/go-couchbase
 | 
					github.com/couchbaselabs/go-couchbase
 | 
				
			||||||
# github.com/davecgh/go-spew v1.1.1
 | 
					# github.com/davecgh/go-spew v1.1.1
 | 
				
			||||||
github.com/davecgh/go-spew/spew
 | 
					github.com/davecgh/go-spew/spew
 | 
				
			||||||
# github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952 => github.com/denisenkom/go-mssqldb v0.0.0-20180314172330-6a30f4e59a44
 | 
					# github.com/denisenkom/go-mssqldb v0.0.0-20190121005146-b04fd42d9952 => github.com/denisenkom/go-mssqldb v0.0.0-20180315180555-6a30f4e59a44
 | 
				
			||||||
github.com/denisenkom/go-mssqldb
 | 
					github.com/denisenkom/go-mssqldb
 | 
				
			||||||
github.com/denisenkom/go-mssqldb/internal/cp
 | 
					github.com/denisenkom/go-mssqldb/internal/cp
 | 
				
			||||||
# github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
					# github.com/dgrijalva/jwt-go v3.2.0+incompatible
 | 
				
			||||||
@@ -120,7 +120,7 @@ github.com/go-macaron/binding
 | 
				
			|||||||
github.com/go-macaron/cache
 | 
					github.com/go-macaron/cache
 | 
				
			||||||
github.com/go-macaron/cache/memcache
 | 
					github.com/go-macaron/cache/memcache
 | 
				
			||||||
github.com/go-macaron/cache/redis
 | 
					github.com/go-macaron/cache/redis
 | 
				
			||||||
# github.com/go-macaron/captcha v0.0.0-20151123225153-8aa5919789ab
 | 
					# github.com/go-macaron/captcha v0.0.0-20190710000913-8dc5911259df
 | 
				
			||||||
github.com/go-macaron/captcha
 | 
					github.com/go-macaron/captcha
 | 
				
			||||||
# github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9
 | 
					# github.com/go-macaron/cors v0.0.0-20190309005821-6fd6a9bfe14e9
 | 
				
			||||||
github.com/go-macaron/cors
 | 
					github.com/go-macaron/cors
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user