mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-11-03 08:02:36 +09:00 
			
		
		
		
	Compare commits
	
		
			84 Commits
		
	
	
		
			v1.14.0-de
			...
			release/v1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					11f6ed4f83 | ||
| 
						 | 
					e94a84248d | ||
| 
						 | 
					cf7a5b3d91 | ||
| 
						 | 
					5d1a8d23b0 | ||
| 
						 | 
					dbd0a2e6dc | ||
| 
						 | 
					7697a282d6 | ||
| 
						 | 
					76e8eec3d9 | ||
| 
						 | 
					10effb396a | ||
| 
						 | 
					5e97b2d00e | ||
| 
						 | 
					873acd884d | ||
| 
						 | 
					dc73b2748d | ||
| 
						 | 
					31ad8b7026 | ||
| 
						 | 
					d07edc5336 | ||
| 
						 | 
					63cb160cb1 | ||
| 
						 | 
					8d5c3d3d0b | ||
| 
						 | 
					706d85b87d | ||
| 
						 | 
					75e491c03e | ||
| 
						 | 
					608f46e59c | ||
| 
						 | 
					895764e7f5 | ||
| 
						 | 
					21983965d0 | ||
| 
						 | 
					e069a75817 | ||
| 
						 | 
					ebb8fa610c | ||
| 
						 | 
					c8fc7fce4a | ||
| 
						 | 
					57b226e284 | ||
| 
						 | 
					5f20841bc3 | ||
| 
						 | 
					40dc7342cf | ||
| 
						 | 
					6d2f0e555e | ||
| 
						 | 
					476ca67cd4 | ||
| 
						 | 
					96eb99ea55 | ||
| 
						 | 
					83560bf9d0 | ||
| 
						 | 
					6b29a6b6f2 | ||
| 
						 | 
					74eee64b57 | ||
| 
						 | 
					d21dabab4e | ||
| 
						 | 
					34ba1c8957 | ||
| 
						 | 
					98d82a7dd9 | ||
| 
						 | 
					ee163a8af1 | ||
| 
						 | 
					ed96b84b2e | ||
| 
						 | 
					7284829962 | ||
| 
						 | 
					21fb791747 | ||
| 
						 | 
					8b3aad940e | ||
| 
						 | 
					81adf6ad86 | ||
| 
						 | 
					e6cd4f3276 | ||
| 
						 | 
					30226b4793 | ||
| 
						 | 
					aecd9231ba | ||
| 
						 | 
					26c1550643 | ||
| 
						 | 
					5f6b118007 | ||
| 
						 | 
					b1cb52e477 | ||
| 
						 | 
					799f5e05c9 | ||
| 
						 | 
					497f37bffd | ||
| 
						 | 
					d7aa553f1b | ||
| 
						 | 
					ba12463175 | ||
| 
						 | 
					0acaa6bd00 | ||
| 
						 | 
					66a3353c31 | ||
| 
						 | 
					5236d8a936 | ||
| 
						 | 
					5876e37ed4 | ||
| 
						 | 
					3c21a0ee80 | ||
| 
						 | 
					f43783f003 | ||
| 
						 | 
					b9c5a3acc3 | ||
| 
						 | 
					c363ef5da0 | ||
| 
						 | 
					e8ca2da08f | ||
| 
						 | 
					f64b8eb009 | ||
| 
						 | 
					40f41dc694 | ||
| 
						 | 
					a63b9fbc70 | ||
| 
						 | 
					4b87aa367c | ||
| 
						 | 
					72f4cdf868 | ||
| 
						 | 
					5be1b7df3f | ||
| 
						 | 
					95e12be30f | ||
| 
						 | 
					245089b9c9 | ||
| 
						 | 
					2551660f49 | ||
| 
						 | 
					3b28de7d8e | ||
| 
						 | 
					3725eefb7f | ||
| 
						 | 
					73ce02400c | ||
| 
						 | 
					197cbd674d | ||
| 
						 | 
					4a0f7c1eb4 | ||
| 
						 | 
					e54f7a708c | ||
| 
						 | 
					63f6764dce | ||
| 
						 | 
					0bf7ed55be | ||
| 
						 | 
					93e8174e4e | ||
| 
						 | 
					c5ec66a8a3 | ||
| 
						 | 
					b6fb082b78 | ||
| 
						 | 
					3ce195115b | ||
| 
						 | 
					00619a04f7 | ||
| 
						 | 
					16815306ad | ||
| 
						 | 
					3934d9cd2f | 
							
								
								
									
										75
									
								
								.drone.yml
									
									
									
									
									
								
							
							
						
						
									
										75
									
								
								.drone.yml
									
									
									
									
									
								
							@@ -2,13 +2,12 @@ workspace:
 | 
				
			|||||||
  base: /go
 | 
					  base: /go
 | 
				
			||||||
  path: src/code.gitea.io/gitea
 | 
					  path: src/code.gitea.io/gitea
 | 
				
			||||||
 | 
					
 | 
				
			||||||
clone:
 | 
					 | 
				
			||||||
  git:
 | 
					 | 
				
			||||||
    image: plugins/git:next
 | 
					 | 
				
			||||||
    depth: 50
 | 
					 | 
				
			||||||
    tags: true
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
pipeline:
 | 
					pipeline:
 | 
				
			||||||
 | 
					  fetch-tags:
 | 
				
			||||||
 | 
					    image: docker:git
 | 
				
			||||||
 | 
					    commands:
 | 
				
			||||||
 | 
					      - git fetch --tags --force
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  download_translations:
 | 
					  download_translations:
 | 
				
			||||||
    image: jonasfranz/crowdin
 | 
					    image: jonasfranz/crowdin
 | 
				
			||||||
    pull: true
 | 
					    pull: true
 | 
				
			||||||
@@ -211,41 +210,41 @@ pipeline:
 | 
				
			|||||||
    when:
 | 
					    when:
 | 
				
			||||||
      event: [ push, tag, pull_request ]
 | 
					      event: [ push, tag, pull_request ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bench-sqlite:
 | 
					#  bench-sqlite:
 | 
				
			||||||
    image: golang:1.12
 | 
					#    image: golang:1.12
 | 
				
			||||||
    pull: true
 | 
					#    pull: true
 | 
				
			||||||
    group: bench
 | 
					#    group: bench
 | 
				
			||||||
    commands:
 | 
					#    commands:
 | 
				
			||||||
      - make bench-sqlite
 | 
					#      - make bench-sqlite
 | 
				
			||||||
    when:
 | 
					#    when:
 | 
				
			||||||
      event: [ tag ]
 | 
					#      event: [ tag ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bench-mysql:
 | 
					#  bench-mysql:
 | 
				
			||||||
    image: golang:1.12
 | 
					#    image: golang:1.12
 | 
				
			||||||
    pull: true
 | 
					#    pull: true
 | 
				
			||||||
    group: bench
 | 
					#    group: bench
 | 
				
			||||||
    commands:
 | 
					#    commands:
 | 
				
			||||||
      - make bench-mysql
 | 
					#      - make bench-mysql
 | 
				
			||||||
    when:
 | 
					#    when:
 | 
				
			||||||
      event: [ tag ]
 | 
					#      event: [ tag ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bench-mssql:
 | 
					#  bench-mssql:
 | 
				
			||||||
    image: golang:1.12
 | 
					#    image: golang:1.12
 | 
				
			||||||
    pull: true
 | 
					#    pull: true
 | 
				
			||||||
    group: bench
 | 
					#    group: bench
 | 
				
			||||||
    commands:
 | 
					#    commands:
 | 
				
			||||||
      - make bench-mssql
 | 
					#      - make bench-mssql
 | 
				
			||||||
    when:
 | 
					#    when:
 | 
				
			||||||
      event: [ tag ]
 | 
					#      event: [ tag ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bench-pgsql:
 | 
					#  bench-pgsql:
 | 
				
			||||||
    image: golang:1.12
 | 
					#    image: golang:1.12
 | 
				
			||||||
    pull: true
 | 
					#    pull: true
 | 
				
			||||||
    group: bench
 | 
					#    group: bench
 | 
				
			||||||
    commands:
 | 
					#    commands:
 | 
				
			||||||
      - make bench-pgsql
 | 
					#      - make bench-pgsql
 | 
				
			||||||
    when:
 | 
					#    when:
 | 
				
			||||||
      event: [ tag ]
 | 
					#      event: [ tag ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  generate-coverage:
 | 
					  generate-coverage:
 | 
				
			||||||
    image: golang:1.12
 | 
					    image: golang:1.12
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										93
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						
									
										93
									
								
								CHANGELOG.md
									
									
									
									
									
								
							@@ -4,7 +4,62 @@ 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.8.0-rc1](https://github.com/go-gitea/gitea/releases/tag/v1.8.0-rc1) - 2019-03-18
 | 
					## [1.8.3](https://github.com/go-gitea/gitea/releases/tag/v1.8.3) - 2019-06-17
 | 
				
			||||||
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Always set userID on LFS authentication (#7224) (Part of #6993)
 | 
				
			||||||
 | 
					  * Fix LFS Locks over SSH (#6999) (#7223)
 | 
				
			||||||
 | 
					  * Fix duplicated file on pull request conflicted files (#7211) (#7214)
 | 
				
			||||||
 | 
					  * Detect noreply email address as user (#7133) (#7195)
 | 
				
			||||||
 | 
					  * Don't get milestone from DB if ID is zero (#7169) (#7174)
 | 
				
			||||||
 | 
					  * Allow archived repos to be (un)starred and (un)watched (#7163) (#7168)
 | 
				
			||||||
 | 
					  * Fix GCArgs load from ini (#7156) (#7157)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.2](https://github.com/go-gitea/gitea/releases/tag/v1.8.2) - 2019-05-29
 | 
				
			||||||
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Fix possbile mysql invalid connnection error (#7051) (#7071)
 | 
				
			||||||
 | 
					  * Handle invalid administrator username on install page (#7060) (#7063)
 | 
				
			||||||
 | 
					  * Disable arm7 builds (#7037) (#7042)
 | 
				
			||||||
 | 
					  * Fix default for allowing new organization creation for new users (#7017) (#7034)
 | 
				
			||||||
 | 
					  * SearchRepositoryByName improvements and unification (#6897) (#7002)
 | 
				
			||||||
 | 
					  * Fix u2f registrationlist ToRegistrations() method (#6980) (#6982)
 | 
				
			||||||
 | 
					  * Allow collaborators to view repo owned by private org (#6965) (#6968)
 | 
				
			||||||
 | 
					  * Use AppURL for Oauth user link (#6894) (#6925)
 | 
				
			||||||
 | 
					  * Escape the commit message on issues update (#6901) (#6902)
 | 
				
			||||||
 | 
					  * Fix regression for API users search (#6882) (#6885)
 | 
				
			||||||
 | 
					  * Handle early git version's lack of get-url (#7065) (#7076)
 | 
				
			||||||
 | 
					  * Fix wrong init dependency on markup extensions (#7038) (#7074)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.1](https://github.com/go-gitea/gitea/releases/tag/v1.8.1) - 2019-05-08
 | 
				
			||||||
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Fix 404 when sending pull requests in some situations (#6871) (#6873)
 | 
				
			||||||
 | 
					  * Enforce osusergo build tag for releases (#6862) (#6869)
 | 
				
			||||||
 | 
					  * Don't post process commit summary in templates (#6842) (#6868)
 | 
				
			||||||
 | 
					  * Fix 500 when reviewer is deleted (#6856) (#6860)
 | 
				
			||||||
 | 
					  * Fix v78 migration for MSSQL (#6823) (#6854)
 | 
				
			||||||
 | 
					  * Added tags pull step to drone config to show correct version hashes (#6836) (#6839)
 | 
				
			||||||
 | 
					  * Fix double-generation of scratch token (#6833) (#6835)
 | 
				
			||||||
 | 
					  * When mirroring we should set the remote to mirror (#6824) (#6834)
 | 
				
			||||||
 | 
					  * Show scrollbar only when needed (#6802) (#6803)
 | 
				
			||||||
 | 
					  * Service worker js is missing a comma (#6788) (#6795)
 | 
				
			||||||
 | 
					  * Set user search base field optional in LDAP (simple auth) edit page (#6779) (#6789)
 | 
				
			||||||
 | 
					  * Fix team edit API panic (#6780) (#6785)
 | 
				
			||||||
 | 
					  * Minor CSS cleanup for the navbar (#6553) (#6781)
 | 
				
			||||||
 | 
					  * Stricter domain name pattern in email regex (#6739) (#6768)
 | 
				
			||||||
 | 
					  * Detect and restore encoding and BOM in content (#6727) (#6765)
 | 
				
			||||||
 | 
					  * Fix org visibility bug when git cloning (#6743) (#6762)
 | 
				
			||||||
 | 
					  * OAuth2 token can be used in basic auth (#6747) (#6761)
 | 
				
			||||||
 | 
					  * Fix missing return (#6751) (#6756)
 | 
				
			||||||
 | 
					  * Fix sorting repos on org home page with non-admin login (#6741) (#6746)
 | 
				
			||||||
 | 
					  * Drop is_bare IDX only when it exists for MySQL and MariaDB (#6736) (#6744)
 | 
				
			||||||
 | 
					  * Fix team members API (#6714) (#6729)
 | 
				
			||||||
 | 
					  * Load issue attributes when editing an issue with API (#6723) (#6725)
 | 
				
			||||||
 | 
					  * Fix config ui error about cache ttl (#6861) (#6865)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.8.0](https://github.com/go-gitea/gitea/releases/tag/v1.8.0) - 2019-04-20
 | 
				
			||||||
 | 
					* SECURITY
 | 
				
			||||||
 | 
					  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6594)
 | 
				
			||||||
 | 
					  * Resolve 2FA bypass on API (#6676) (#6674)
 | 
				
			||||||
 | 
					  * Prevent the creation of empty sessions for non-logged in users (#6690) (#6677)
 | 
				
			||||||
* BREAKING
 | 
					* BREAKING
 | 
				
			||||||
  * Add "ghost" and "notifications" to list of reserved user names. (#6208)
 | 
					  * Add "ghost" and "notifications" to list of reserved user names. (#6208)
 | 
				
			||||||
  * Change sqlite DB path default to data directory (#6198)
 | 
					  * Change sqlite DB path default to data directory (#6198)
 | 
				
			||||||
@@ -84,7 +139,31 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			|||||||
  * Allow markdown table to scroll (#4401)
 | 
					  * Allow markdown table to scroll (#4401)
 | 
				
			||||||
  * Automatically clear stopwatch on merging a PR (#4327)
 | 
					  * Automatically clear stopwatch on merging a PR (#4327)
 | 
				
			||||||
  * Add the Owner Name to differentiate when merging (#3807)
 | 
					  * Add the Owner Name to differentiate when merging (#3807)
 | 
				
			||||||
 | 
					  * Add title attributes to all items in the repo list viewer (#6258) (#6650)
 | 
				
			||||||
* BUGFIXES
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Fix dropdown icon padding (#6651) (#6654)
 | 
				
			||||||
 | 
					  * Fix wrong GPG expire date (#6643) (#6644)
 | 
				
			||||||
 | 
					  * Fix forking an empty repository (#6637) (#6653)
 | 
				
			||||||
 | 
					  * Remove call to EscapePound .Link as it is already escaped (#6656) (#6666)
 | 
				
			||||||
 | 
					  * Properly escape on the redirect from the web editor (#6657) (#6667)
 | 
				
			||||||
 | 
					  * Allow resend of confirmation email when logged in (#6482) (#6486)
 | 
				
			||||||
 | 
					  * Fix mail notification when close/reopen issue (#6581) (#6588)
 | 
				
			||||||
 | 
					  * Change API commit summary to full message (#6591) (#6592)
 | 
				
			||||||
 | 
					  * Add option to disable refresh token invalidation (#6584) (#6587)
 | 
				
			||||||
 | 
					  * Fix bug user search API pagesize didn't obey ExplorePagingNum (#6579) (#6586)
 | 
				
			||||||
 | 
					  * Fix new repo alignment (#6583) (#6585)
 | 
				
			||||||
 | 
					  * Prevent server 500 on compare branches with no common history (#6555) (#6558)
 | 
				
			||||||
 | 
					  * Properly escape release attachment URL (#6512) (#6523)
 | 
				
			||||||
 | 
					  * Hacky fix for alignment of the create-organization dialog (#6455) (#6462)
 | 
				
			||||||
 | 
					  * Disable benchmarking during tag events on DroneIO (#6365) (#6366)
 | 
				
			||||||
 | 
					  * Make sure units of a team are returned (#6379) (#6381)
 | 
				
			||||||
 | 
					  * Don't Unescape redirect_to cookie value (#6399) (#6401)
 | 
				
			||||||
 | 
					  * Fix dump table name error and add some test for dump database (#6394) (#6402)
 | 
				
			||||||
 | 
					  * Fix migration v82 to ignore unsynced tags between database and git data; Add missing is_archived column on repository table (#6387) (#6403)
 | 
				
			||||||
 | 
					  * Display correct error for invalid mirror interval (#6414) (#6429)
 | 
				
			||||||
 | 
					  * Clean up ref name rules (#6437) (#6439)
 | 
				
			||||||
 | 
					  * Fix Hook & HookList in Swagger (#6432) (#6440)
 | 
				
			||||||
 | 
					  * Change order that PostProcess Processors are run (#6445) (#6447)
 | 
				
			||||||
  * Clean up various use of escape/unescape functions for URL generation (#6334)
 | 
					  * Clean up various use of escape/unescape functions for URL generation (#6334)
 | 
				
			||||||
  * Return 409 when creating repo if it already exists. (#6330)
 | 
					  * Return 409 when creating repo if it already exists. (#6330)
 | 
				
			||||||
  * Add same changes from issues page to milestone->issues page (#6328)
 | 
					  * Add same changes from issues page to milestone->issues page (#6328)
 | 
				
			||||||
@@ -210,6 +289,18 @@ been added to each release, please refer to the [blog](https://blog.gitea.io).
 | 
				
			|||||||
  * Add missing GET teams endpoints (#5382)
 | 
					  * Add missing GET teams endpoints (#5382)
 | 
				
			||||||
  * Migrate database if app.ini found (#5290)
 | 
					  * Migrate database if app.ini found (#5290)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.7.6](https://github.com/go-gitea/gitea/releases/tag/v1.7.6) - 2019-04-12
 | 
				
			||||||
 | 
					* SECURITY
 | 
				
			||||||
 | 
					  * Prevent remote code execution vulnerability with mirror repo URL settings (#6593) (#6595)
 | 
				
			||||||
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Allow resend of confirmation email when logged in (#6482) (#6487)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## [1.7.5](https://github.com/go-gitea/gitea/releases/tag/v1.7.5) - 2019-03-27
 | 
				
			||||||
 | 
					* BUGFIXES
 | 
				
			||||||
 | 
					  * Fix unitTypeCode not being used in accessLevelUnit (#6419) (#6423)
 | 
				
			||||||
 | 
					  * Fix bug where manifest.json was being requested without cookies and continuously creating new sessions (#6372) (#6383) 
 | 
				
			||||||
 | 
					  * Fix ParsePatch function to work with quoted diff --git strings (#6323) (#6332)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
 | 
					## [1.7.4](https://github.com/go-gitea/gitea/releases/tag/v1.7.4) - 2019-03-12
 | 
				
			||||||
* SECURITY
 | 
					* SECURITY
 | 
				
			||||||
  * Fix potential XSS vulnerability in repository description. (#6306) (#6308)
 | 
					  * Fix potential XSS vulnerability in repository description. (#6306) (#6308)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										4
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										4
									
								
								Gopkg.lock
									
									
									
										generated
									
									
									
								
							@@ -3,11 +3,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  branch = "master"
 | 
					  branch = "master"
 | 
				
			||||||
  digest = "1:e1fa64238b0a2dbf1edf98c4af8d1b8cb65179e286d7f28006b50fa9f508ee9d"
 | 
					  digest = "1:c298eea5ff7f6ab40cda6fe75d2224e2dd271941abe2f66276063b39e43e5687"
 | 
				
			||||||
  name = "code.gitea.io/git"
 | 
					  name = "code.gitea.io/git"
 | 
				
			||||||
  packages = ["."]
 | 
					  packages = ["."]
 | 
				
			||||||
  pruneopts = "NUT"
 | 
					  pruneopts = "NUT"
 | 
				
			||||||
  revision = "74d7c14dd4a3ed9c5def0dc3c1aeede399ddc5c5"
 | 
					  revision = "63b74d438b29bb272fa9b4010abe3f50a832e7ef"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
[[projects]]
 | 
					[[projects]]
 | 
				
			||||||
  branch = "master"
 | 
					  branch = "master"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										21
									
								
								Makefile
									
									
									
									
									
								
							@@ -3,6 +3,7 @@ IMPORT := code.gitea.io/gitea
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
GO ?= go
 | 
					GO ?= go
 | 
				
			||||||
SED_INPLACE := sed -i
 | 
					SED_INPLACE := sed -i
 | 
				
			||||||
 | 
					SHASUM ?= shasum -a 256
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export PATH := $($(GO) env GOPATH)/bin:$(PATH)
 | 
					export PATH := $($(GO) env GOPATH)/bin:$(PATH)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -148,7 +149,7 @@ misspell-check:
 | 
				
			|||||||
	@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
						@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
				
			||||||
		$(GO) get -u github.com/client9/misspell/cmd/misspell; \
 | 
							$(GO) get -u github.com/client9/misspell/cmd/misspell; \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	misspell -error -i unknwon $(GOFILES)
 | 
						misspell -error -i unknwon,destory $(GOFILES)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: misspell
 | 
					.PHONY: misspell
 | 
				
			||||||
misspell:
 | 
					misspell:
 | 
				
			||||||
@@ -325,9 +326,9 @@ release-windows:
 | 
				
			|||||||
	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
						@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
				
			||||||
		$(GO) get -u src.techknowlogick.com/xgo; \
 | 
							$(GO) get -u src.techknowlogick.com/xgo; \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
 | 
						xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'windows/*' -out gitea-$(VERSION) .
 | 
				
			||||||
ifeq ($(CI),drone)
 | 
					ifeq ($(CI),drone)
 | 
				
			||||||
	mv /build/* $(DIST)/binaries
 | 
						cp /build/* $(DIST)/binaries
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: release-linux
 | 
					.PHONY: release-linux
 | 
				
			||||||
@@ -335,9 +336,9 @@ release-linux:
 | 
				
			|||||||
	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
						@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
				
			||||||
		$(GO) get -u src.techknowlogick.com/xgo; \
 | 
							$(GO) get -u src.techknowlogick.com/xgo; \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/*' -out gitea-$(VERSION) .
 | 
						xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '-linkmode external -extldflags "-static" $(LDFLAGS)' -targets 'linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64,linux/mips64le,linux/mips,linux/mipsle' -out gitea-$(VERSION) .
 | 
				
			||||||
ifeq ($(CI),drone)
 | 
					ifeq ($(CI),drone)
 | 
				
			||||||
	mv /build/* $(DIST)/binaries
 | 
						cp /build/* $(DIST)/binaries
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: release-darwin
 | 
					.PHONY: release-darwin
 | 
				
			||||||
@@ -345,25 +346,25 @@ release-darwin:
 | 
				
			|||||||
	@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
						@hash xgo > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
				
			||||||
		$(GO) get -u src.techknowlogick.com/xgo; \
 | 
							$(GO) get -u src.techknowlogick.com/xgo; \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	xgo -dest $(DIST)/binaries -tags 'netgo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
 | 
						xgo -dest $(DIST)/binaries -tags 'netgo osusergo $(TAGS)' -ldflags '$(LDFLAGS)' -targets 'darwin/*' -out gitea-$(VERSION) .
 | 
				
			||||||
ifeq ($(CI),drone)
 | 
					ifeq ($(CI),drone)
 | 
				
			||||||
	mv /build/* $(DIST)/binaries
 | 
						cp /build/* $(DIST)/binaries
 | 
				
			||||||
endif
 | 
					endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: release-copy
 | 
					.PHONY: release-copy
 | 
				
			||||||
release-copy:
 | 
					release-copy:
 | 
				
			||||||
	$(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),cp $(file) $(DIST)/release/$(notdir $(file));)
 | 
						cd $(DIST); for file in `find /build -type f -name "*"`; do cp $${file} ./release/; done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: release-check
 | 
					.PHONY: release-check
 | 
				
			||||||
release-check:
 | 
					release-check:
 | 
				
			||||||
	cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
 | 
						cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "checksumming $${file}" && $(SHASUM) `echo $${file} | sed 's/^..//'` > $${file}.sha256; done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: release-compress
 | 
					.PHONY: release-compress
 | 
				
			||||||
release-compress:
 | 
					release-compress:
 | 
				
			||||||
	@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
						@hash gxz > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
 | 
				
			||||||
		$(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \
 | 
							$(GO) get -u github.com/ulikunitz/xz/cmd/gxz; \
 | 
				
			||||||
	fi
 | 
						fi
 | 
				
			||||||
	cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/binaries/$(EXECUTABLE)-*),gxz -k -9 $(notdir $(file));)
 | 
						cd $(DIST)/release/; for file in `find . -type f -name "*"`; do echo "compressing $${file}" && gxz -k -9 $${file}; done;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.PHONY: javascripts
 | 
					.PHONY: javascripts
 | 
				
			||||||
javascripts: public/js/index.js
 | 
					javascripts: public/js/index.js
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										130
									
								
								cmd/serv.go
									
									
									
									
									
								
							
							
						
						
									
										130
									
								
								cmd/serv.go
									
									
									
									
									
								
							@@ -217,75 +217,77 @@ func runServ(c *cli.Context) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	// Allow anonymous clone for public repositories.
 | 
						// Allow anonymous clone for public repositories.
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		keyID int64
 | 
							keyID  int64
 | 
				
			||||||
		user  *models.User
 | 
							user   *models.User
 | 
				
			||||||
 | 
							userID int64
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView {
 | 
					 | 
				
			||||||
		keys := strings.Split(c.Args()[0], "-")
 | 
					 | 
				
			||||||
		if len(keys) != 2 {
 | 
					 | 
				
			||||||
			fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
 | 
						keys := strings.Split(c.Args()[0], "-")
 | 
				
			||||||
 | 
						if len(keys) != 2 {
 | 
				
			||||||
 | 
							fail("Key ID format error", "Invalid key argument: %s", c.Args()[0])
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						key, err := private.GetPublicKeyByID(com.StrTo(keys[1]).MustInt64())
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						keyID = key.ID
 | 
				
			||||||
 | 
						userID = key.OwnerID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if key.Type == models.KeyTypeDeploy {
 | 
				
			||||||
 | 
							// Now we have to get the deploy key for this repo
 | 
				
			||||||
 | 
							deployKey, err := private.GetDeployKey(key.ID, repo.ID)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			fail("Invalid key ID", "Invalid key ID[%s]: %v", c.Args()[0], err)
 | 
								fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		keyID = key.ID
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if deployKey == nil {
 | 
				
			||||||
 | 
								fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if deployKey.Mode < requestedMode {
 | 
				
			||||||
 | 
								fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Update deploy key activity.
 | 
				
			||||||
 | 
							if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
 | 
				
			||||||
 | 
								fail("Internal error", "UpdateDeployKey: %v", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// FIXME: Deploy keys aren't really the owner of the repo pushing changes
 | 
				
			||||||
 | 
							// however we don't have good way of representing deploy keys in hook.go
 | 
				
			||||||
 | 
							// so for now use the owner
 | 
				
			||||||
 | 
							os.Setenv(models.EnvPusherName, username)
 | 
				
			||||||
 | 
							os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
 | 
				
			||||||
 | 
							userID = repo.OwnerID
 | 
				
			||||||
 | 
						} else if requestedMode == models.AccessModeWrite || repo.IsPrivate || setting.Service.RequireSignInView {
 | 
				
			||||||
		// Check deploy key or user key.
 | 
							// Check deploy key or user key.
 | 
				
			||||||
		if key.Type == models.KeyTypeDeploy {
 | 
							user, err = private.GetUserByKeyID(key.ID)
 | 
				
			||||||
			// Now we have to get the deploy key for this repo
 | 
							if err != nil {
 | 
				
			||||||
			deployKey, err := private.GetDeployKey(key.ID, repo.ID)
 | 
								fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				fail("Key access denied", "Failed to access internal api: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if deployKey == nil {
 | 
					 | 
				
			||||||
				fail("Key access denied", "Deploy key access denied: [key_id: %d, repo_id: %d]", key.ID, repo.ID)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if deployKey.Mode < requestedMode {
 | 
					 | 
				
			||||||
				fail("Key permission denied", "Cannot push with read-only deployment key: %d to repo_id: %d", key.ID, repo.ID)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// Update deploy key activity.
 | 
					 | 
				
			||||||
			if err = private.UpdateDeployKeyUpdated(key.ID, repo.ID); err != nil {
 | 
					 | 
				
			||||||
				fail("Internal error", "UpdateDeployKey: %v", err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			// FIXME: Deploy keys aren't really the owner of the repo pushing changes
 | 
					 | 
				
			||||||
			// however we don't have good way of representing deploy keys in hook.go
 | 
					 | 
				
			||||||
			// so for now use the owner
 | 
					 | 
				
			||||||
			os.Setenv(models.EnvPusherName, username)
 | 
					 | 
				
			||||||
			os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", repo.OwnerID))
 | 
					 | 
				
			||||||
		} else {
 | 
					 | 
				
			||||||
			user, err = private.GetUserByKeyID(key.ID)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				fail("internal error", "Failed to get user by key ID(%d): %v", keyID, err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if !user.IsActive || user.ProhibitLogin {
 | 
					 | 
				
			||||||
				fail("Your account is not active or has been disabled by Administrator",
 | 
					 | 
				
			||||||
					"User %s is disabled and have no access to repository %s",
 | 
					 | 
				
			||||||
					user.Name, repoPath)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				fail("Internal error", "Failed to check access: %v", err)
 | 
					 | 
				
			||||||
			} else if *mode < requestedMode {
 | 
					 | 
				
			||||||
				clientMessage := accessDenied
 | 
					 | 
				
			||||||
				if *mode >= models.AccessModeRead {
 | 
					 | 
				
			||||||
					clientMessage = "You do not have sufficient authorization for this action"
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				fail(clientMessage,
 | 
					 | 
				
			||||||
					"User %s does not have level %v access to repository %s's "+unitName,
 | 
					 | 
				
			||||||
					user.Name, requestedMode, repoPath)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			os.Setenv(models.EnvPusherName, user.Name)
 | 
					 | 
				
			||||||
			os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if !user.IsActive || user.ProhibitLogin {
 | 
				
			||||||
 | 
								fail("Your account is not active or has been disabled by Administrator",
 | 
				
			||||||
 | 
									"User %s is disabled and have no access to repository %s",
 | 
				
			||||||
 | 
									user.Name, repoPath)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							mode, err := private.CheckUnitUser(user.ID, repo.ID, user.IsAdmin, unitType)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fail("Internal error", "Failed to check access: %v", err)
 | 
				
			||||||
 | 
							} else if *mode < requestedMode {
 | 
				
			||||||
 | 
								clientMessage := accessDenied
 | 
				
			||||||
 | 
								if *mode >= models.AccessModeRead {
 | 
				
			||||||
 | 
									clientMessage = "You do not have sufficient authorization for this action"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								fail(clientMessage,
 | 
				
			||||||
 | 
									"User %s does not have level %v access to repository %s's "+unitName,
 | 
				
			||||||
 | 
									user.Name, requestedMode, repoPath)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							os.Setenv(models.EnvPusherName, user.Name)
 | 
				
			||||||
 | 
							os.Setenv(models.EnvPusherID, fmt.Sprintf("%d", user.ID))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//LFS token authentication
 | 
						//LFS token authentication
 | 
				
			||||||
@@ -299,8 +301,8 @@ func runServ(c *cli.Context) error {
 | 
				
			|||||||
			"exp":  now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
 | 
								"exp":  now.Add(setting.LFS.HTTPAuthExpiry).Unix(),
 | 
				
			||||||
			"nbf":  now.Unix(),
 | 
								"nbf":  now.Unix(),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if user != nil {
 | 
							if userID > 0 {
 | 
				
			||||||
			claims["user"] = user.ID
 | 
								claims["user"] = userID
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
 | 
							token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -15,7 +15,6 @@ import (
 | 
				
			|||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/modules/log"
 | 
						"code.gitea.io/gitea/modules/log"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup/external"
 | 
					 | 
				
			||||||
	"code.gitea.io/gitea/modules/setting"
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
	"code.gitea.io/gitea/routers"
 | 
						"code.gitea.io/gitea/routers"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/routes"
 | 
						"code.gitea.io/gitea/routers/routes"
 | 
				
			||||||
@@ -120,8 +119,6 @@ func runWeb(ctx *cli.Context) error {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	routers.GlobalInit()
 | 
						routers.GlobalInit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	external.RegisterParsers()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	m := routes.NewMacaron()
 | 
						m := routes.NewMacaron()
 | 
				
			||||||
	routes.RegisterRoutes(m)
 | 
						routes.RegisterRoutes(m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,6 +20,7 @@ import (
 | 
				
			|||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/markup"
 | 
				
			||||||
	"code.gitea.io/gitea/modules/markup/external"
 | 
						"code.gitea.io/gitea/modules/markup/external"
 | 
				
			||||||
	"code.gitea.io/gitea/routers"
 | 
						"code.gitea.io/gitea/routers"
 | 
				
			||||||
	"code.gitea.io/gitea/routers/routes"
 | 
						"code.gitea.io/gitea/routers/routes"
 | 
				
			||||||
@@ -113,6 +114,7 @@ func runPR() {
 | 
				
			|||||||
	log.Printf("[PR] Setting up router\n")
 | 
						log.Printf("[PR] Setting up router\n")
 | 
				
			||||||
	//routers.GlobalInit()
 | 
						//routers.GlobalInit()
 | 
				
			||||||
	external.RegisterParsers()
 | 
						external.RegisterParsers()
 | 
				
			||||||
 | 
						markup.Init()
 | 
				
			||||||
	m := routes.NewMacaron()
 | 
						m := routes.NewMacaron()
 | 
				
			||||||
	routes.RegisterRoutes(m)
 | 
						routes.RegisterRoutes(m)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -661,6 +661,8 @@ ENABLED = true
 | 
				
			|||||||
ACCESS_TOKEN_EXPIRATION_TIME=3600
 | 
					ACCESS_TOKEN_EXPIRATION_TIME=3600
 | 
				
			||||||
; Lifetime of an OAuth2 access token in hours
 | 
					; Lifetime of an OAuth2 access token in hours
 | 
				
			||||||
REFRESH_TOKEN_EXPIRATION_TIME=730
 | 
					REFRESH_TOKEN_EXPIRATION_TIME=730
 | 
				
			||||||
 | 
					; Check if refresh token got already used
 | 
				
			||||||
 | 
					INVALIDATE_REFRESH_TOKENS=false
 | 
				
			||||||
; OAuth2 authentication secret for access and refresh tokens, change this a unique string.
 | 
					; OAuth2 authentication secret for access and refresh tokens, change this a unique string.
 | 
				
			||||||
JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
 | 
					JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -350,6 +350,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
 | 
				
			|||||||
- `ENABLED`: **true**: Enables OAuth2 provider.
 | 
					- `ENABLED`: **true**: Enables OAuth2 provider.
 | 
				
			||||||
- `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds
 | 
					- `ACCESS_TOKEN_EXPIRATION_TIME`: **3600**: Lifetime of an OAuth2 access token in seconds
 | 
				
			||||||
- `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 access token in hours
 | 
					- `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 access token in hours
 | 
				
			||||||
 | 
					- `INVALIDATE_REFRESH_TOKEN`: **false**: Check if refresh token got already used
 | 
				
			||||||
- `JWT_SECRET`: **\<empty\>**: OAuth2 authentication secret for access and refresh tokens, change this a unique string.
 | 
					- `JWT_SECRET`: **\<empty\>**: OAuth2 authentication secret for access and refresh tokens, change this a unique string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## i18n (`i18n`)
 | 
					## i18n (`i18n`)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -115,6 +115,10 @@ Both the LDAP via BindDN and the simple auth LDAP share the following fields:
 | 
				
			|||||||
  - Example: `cn=%s,ou=Users,dc=mydomain,dc=com`
 | 
					  - Example: `cn=%s,ou=Users,dc=mydomain,dc=com`
 | 
				
			||||||
  - Example: `uid=%s,ou=Users,dc=mydomain,dc=com`
 | 
					  - Example: `uid=%s,ou=Users,dc=mydomain,dc=com`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- User Search Base  (optional)
 | 
				
			||||||
 | 
					  - The LDAP base at which user accounts will be searched for.
 | 
				
			||||||
 | 
					  - Example: `ou=Users,dc=mydomain,dc=com`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
- User Filter **(required)**
 | 
					- User Filter **(required)**
 | 
				
			||||||
  - An LDAP filter declaring when a user should be allowed to log in. The `%s`
 | 
					  - An LDAP filter declaring when a user should be allowed to log in. The `%s`
 | 
				
			||||||
    matching parameter will be substituted with login name given on sign-in
 | 
					    matching parameter will be substituted with login name given on sign-in
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -106,3 +106,41 @@ func TestAPISudoUserForbidden(t *testing.T) {
 | 
				
			|||||||
	req := NewRequest(t, "GET", urlStr)
 | 
						req := NewRequest(t, "GET", urlStr)
 | 
				
			||||||
	session.MakeRequest(t, req, http.StatusForbidden)
 | 
						session.MakeRequest(t, req, http.StatusForbidden)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIListUsers(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						adminUsername := "user1"
 | 
				
			||||||
 | 
						session := loginUser(t, adminUsername)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						urlStr := fmt.Sprintf("/api/v1/admin/users?token=%s", token)
 | 
				
			||||||
 | 
						req := NewRequest(t, "GET", urlStr)
 | 
				
			||||||
 | 
						resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
						var users []api.User
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &users)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						found := false
 | 
				
			||||||
 | 
						for _, user := range users {
 | 
				
			||||||
 | 
							if user.UserName == adminUsername {
 | 
				
			||||||
 | 
								found = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						assert.True(t, found)
 | 
				
			||||||
 | 
						numberOfUsers := models.GetCount(t, &models.User{}, "type = 0")
 | 
				
			||||||
 | 
						assert.Equal(t, numberOfUsers, len(users))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIListUsersNotLoggedIn(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						req := NewRequest(t, "GET", "/api/v1/admin/users")
 | 
				
			||||||
 | 
						MakeRequest(t, req, http.StatusUnauthorized)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIListUsersNonAdmin(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						nonAdminUsername := "user2"
 | 
				
			||||||
 | 
						session := loginUser(t, nonAdminUsername)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
						req := NewRequestf(t, "GET", "/api/v1/admin/users?token=%s", token)
 | 
				
			||||||
 | 
						session.MakeRequest(t, req, http.StatusForbidden)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -56,3 +56,39 @@ func TestAPIMergePullWIP(t *testing.T) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	session.MakeRequest(t, req, http.StatusMethodNotAllowed)
 | 
						session.MakeRequest(t, req, http.StatusMethodNotAllowed)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPICreatePullSuccess1(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
 | 
				
			||||||
 | 
						// repo10 have code, pulls units.
 | 
				
			||||||
 | 
						repo11 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 11}).(*models.Repository)
 | 
				
			||||||
 | 
						// repo11 only have code unit but should still create pulls
 | 
				
			||||||
 | 
						owner10 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo10.OwnerID}).(*models.User)
 | 
				
			||||||
 | 
						owner11 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo11.OwnerID}).(*models.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session := loginUser(t, owner11.Name)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
						req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
 | 
				
			||||||
 | 
							Head:  fmt.Sprintf("%s:master", owner11.Name),
 | 
				
			||||||
 | 
							Base:  "master",
 | 
				
			||||||
 | 
							Title: "create a failure pr",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session.MakeRequest(t, req, 201)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPICreatePullSuccess2(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository)
 | 
				
			||||||
 | 
						owner10 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo10.OwnerID}).(*models.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session := loginUser(t, owner10.Name)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
						req := NewRequestWithJSON(t, http.MethodPost, fmt.Sprintf("/api/v1/repos/%s/%s/pulls?token=%s", owner10.Name, repo10.Name, token), &api.CreatePullRequestOption{
 | 
				
			||||||
 | 
							Head:  "develop",
 | 
				
			||||||
 | 
							Base:  "master",
 | 
				
			||||||
 | 
							Title: "create a success pr",
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session.MakeRequest(t, req, 201)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -69,40 +69,41 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
		name, requestURL string
 | 
							name, requestURL string
 | 
				
			||||||
		expectedResults
 | 
							expectedResults
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
		{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50", expectedResults: expectedResults{
 | 
							{name: "RepositoriesMax50", requestURL: "/api/v1/repos/search?limit=50&private=false", expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 19},
 | 
								nil:   {count: 19},
 | 
				
			||||||
			user:  {count: 19},
 | 
								user:  {count: 19},
 | 
				
			||||||
			user2: {count: 19}},
 | 
								user2: {count: 19}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10", expectedResults: expectedResults{
 | 
							{name: "RepositoriesMax10", requestURL: "/api/v1/repos/search?limit=10&private=false", expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 10},
 | 
								nil:   {count: 10},
 | 
				
			||||||
			user:  {count: 10},
 | 
								user:  {count: 10},
 | 
				
			||||||
			user2: {count: 10}},
 | 
								user2: {count: 10}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default", expectedResults: expectedResults{
 | 
							{name: "RepositoriesDefaultMax10", requestURL: "/api/v1/repos/search?default&private=false", expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 10},
 | 
								nil:   {count: 10},
 | 
				
			||||||
			user:  {count: 10},
 | 
								user:  {count: 10},
 | 
				
			||||||
			user2: {count: 10}},
 | 
								user2: {count: 10}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s", "big_test_"), expectedResults: expectedResults{
 | 
							{name: "RepositoriesByName", requestURL: fmt.Sprintf("/api/v1/repos/search?q=%s&private=false", "big_test_"), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 7, repoName: "big_test_"},
 | 
								nil:   {count: 7, repoName: "big_test_"},
 | 
				
			||||||
			user:  {count: 7, repoName: "big_test_"},
 | 
								user:  {count: 7, repoName: "big_test_"},
 | 
				
			||||||
			user2: {count: 7, repoName: "big_test_"}},
 | 
								user2: {count: 7, repoName: "big_test_"}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user.ID), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user.ID), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 4},
 | 
								nil:   {count: 5},
 | 
				
			||||||
			user:  {count: 8, includesPrivate: true},
 | 
								user:  {count: 9, includesPrivate: true},
 | 
				
			||||||
			user2: {count: 4}},
 | 
								user2: {count: 5, includesPrivate: true}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser2", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user2.ID), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser2", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user2.ID), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 1},
 | 
								nil:   {count: 1},
 | 
				
			||||||
			user:  {count: 1},
 | 
								user:  {count: 2, includesPrivate: true},
 | 
				
			||||||
			user2: {count: 2, includesPrivate: true}},
 | 
								user2: {count: 2, includesPrivate: true},
 | 
				
			||||||
 | 
								user4: {count: 1}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser3", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user3.ID), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser3", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user3.ID), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 1},
 | 
								nil:   {count: 1},
 | 
				
			||||||
			user:  {count: 1},
 | 
								user:  {count: 4, includesPrivate: true},
 | 
				
			||||||
			user2: {count: 1},
 | 
								user2: {count: 2, includesPrivate: true},
 | 
				
			||||||
			user3: {count: 4, includesPrivate: true}},
 | 
								user3: {count: 4, includesPrivate: true}},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesOwnedByOrganization", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", orgUser.ID), expectedResults: expectedResults{
 | 
							{name: "RepositoriesOwnedByOrganization", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", orgUser.ID), expectedResults: expectedResults{
 | 
				
			||||||
@@ -112,12 +113,12 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser4", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user4.ID), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser4", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d", user4.ID), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 3},
 | 
								nil:   {count: 3},
 | 
				
			||||||
			user:  {count: 3},
 | 
								user:  {count: 4, includesPrivate: true},
 | 
				
			||||||
			user4: {count: 6, includesPrivate: true}}},
 | 
								user4: {count: 7, includesPrivate: true}}},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeSource", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "source"), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeSource", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "source"), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 0},
 | 
								nil:   {count: 0},
 | 
				
			||||||
			user:  {count: 0},
 | 
								user:  {count: 1, includesPrivate: true},
 | 
				
			||||||
			user4: {count: 0, includesPrivate: true}}},
 | 
								user4: {count: 1, includesPrivate: true}}},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeFork", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "fork"), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeFork", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "fork"), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 1},
 | 
								nil:   {count: 1},
 | 
				
			||||||
			user:  {count: 1},
 | 
								user:  {count: 1},
 | 
				
			||||||
@@ -136,8 +137,8 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
			user4: {count: 2, includesPrivate: true}}},
 | 
								user4: {count: 2, includesPrivate: true}}},
 | 
				
			||||||
		{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeCollaborative", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "collaborative"), expectedResults: expectedResults{
 | 
							{name: "RepositoriesAccessibleAndRelatedToUser4/SearchModeCollaborative", requestURL: fmt.Sprintf("/api/v1/repos/search?uid=%d&mode=%s", user4.ID, "collaborative"), expectedResults: expectedResults{
 | 
				
			||||||
			nil:   {count: 0},
 | 
								nil:   {count: 0},
 | 
				
			||||||
			user:  {count: 0},
 | 
								user:  {count: 1, includesPrivate: true},
 | 
				
			||||||
			user4: {count: 0, includesPrivate: true}}},
 | 
								user4: {count: 1, includesPrivate: true}}},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, testCase := range testCases {
 | 
						for _, testCase := range testCases {
 | 
				
			||||||
@@ -164,14 +165,19 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
					var body api.SearchResults
 | 
										var body api.SearchResults
 | 
				
			||||||
					DecodeJSON(t, response, &body)
 | 
										DecodeJSON(t, response, &body)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					assert.Len(t, body.Data, expected.count)
 | 
										repoNames := make([]string, 0, len(body.Data))
 | 
				
			||||||
 | 
										for _, repo := range body.Data {
 | 
				
			||||||
 | 
											repoNames = append(repoNames, fmt.Sprintf("%d:%s:%t", repo.ID, repo.FullName, repo.Private))
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										assert.Len(t, repoNames, expected.count)
 | 
				
			||||||
					for _, repo := range body.Data {
 | 
										for _, repo := range body.Data {
 | 
				
			||||||
						r := getRepo(t, repo.ID)
 | 
											r := getRepo(t, repo.ID)
 | 
				
			||||||
						hasAccess, err := models.HasAccess(userID, r)
 | 
											hasAccess, err := models.HasAccess(userID, r)
 | 
				
			||||||
						assert.NoError(t, err)
 | 
											assert.NoError(t, err, "Error when checking if User: %d has access to %s: %v", userID, repo.FullName, err)
 | 
				
			||||||
						assert.True(t, hasAccess)
 | 
											assert.True(t, hasAccess, "User: %d does not have access to %s", userID, repo.FullName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						assert.NotEmpty(t, repo.Name)
 | 
											assert.NotEmpty(t, repo.Name)
 | 
				
			||||||
 | 
											assert.Equal(t, repo.Name, r.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if len(expected.repoName) > 0 {
 | 
											if len(expected.repoName) > 0 {
 | 
				
			||||||
							assert.Contains(t, repo.Name, expected.repoName)
 | 
												assert.Contains(t, repo.Name, expected.repoName)
 | 
				
			||||||
@@ -182,7 +188,7 @@ func TestAPISearchRepo(t *testing.T) {
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
						if !expected.includesPrivate {
 | 
											if !expected.includesPrivate {
 | 
				
			||||||
							assert.False(t, repo.Private)
 | 
												assert.False(t, repo.Private, "User: %d not expecting private repository: %s", userID, repo.FullName)
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,10 +5,13 @@
 | 
				
			|||||||
package integrations
 | 
					package integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"sort"
 | 
				
			||||||
	"testing"
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"code.gitea.io/gitea/models"
 | 
						"code.gitea.io/gitea/models"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/api/v1/convert"
 | 
				
			||||||
	api "code.gitea.io/sdk/gitea"
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
@@ -16,6 +19,7 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func TestAPITeam(t *testing.T) {
 | 
					func TestAPITeam(t *testing.T) {
 | 
				
			||||||
	prepareTestEnv(t)
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	teamUser := models.AssertExistsAndLoadBean(t, &models.TeamUser{}).(*models.TeamUser)
 | 
						teamUser := models.AssertExistsAndLoadBean(t, &models.TeamUser{}).(*models.TeamUser)
 | 
				
			||||||
	team := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamUser.TeamID}).(*models.Team)
 | 
						team := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamUser.TeamID}).(*models.Team)
 | 
				
			||||||
	user := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser.UID}).(*models.User)
 | 
						user := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser.UID}).(*models.User)
 | 
				
			||||||
@@ -29,4 +33,77 @@ func TestAPITeam(t *testing.T) {
 | 
				
			|||||||
	DecodeJSON(t, resp, &apiTeam)
 | 
						DecodeJSON(t, resp, &apiTeam)
 | 
				
			||||||
	assert.EqualValues(t, team.ID, apiTeam.ID)
 | 
						assert.EqualValues(t, team.ID, apiTeam.ID)
 | 
				
			||||||
	assert.Equal(t, team.Name, apiTeam.Name)
 | 
						assert.Equal(t, team.Name, apiTeam.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// non team member user will not access the teams details
 | 
				
			||||||
 | 
						teamUser2 := models.AssertExistsAndLoadBean(t, &models.TeamUser{ID: 3}).(*models.TeamUser)
 | 
				
			||||||
 | 
						user2 := models.AssertExistsAndLoadBean(t, &models.User{ID: teamUser2.UID}).(*models.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session = loginUser(t, user2.Name)
 | 
				
			||||||
 | 
						token = getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
						req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamUser.TeamID)
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusForbidden)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req = NewRequestf(t, "GET", "/api/v1/teams/%d", teamUser.TeamID)
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusUnauthorized)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Get a member of the owner team able to create, update and delete teams.
 | 
				
			||||||
 | 
						user = models.AssertExistsAndLoadBean(t, &models.User{ID: 5}).(*models.User)
 | 
				
			||||||
 | 
						session = loginUser(t, user.Name)
 | 
				
			||||||
 | 
						token = getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						org := models.AssertExistsAndLoadBean(t, &models.User{ID: 6}).(*models.User)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Create team.
 | 
				
			||||||
 | 
						teamToCreate := &api.CreateTeamOption{
 | 
				
			||||||
 | 
							Name:        "team1",
 | 
				
			||||||
 | 
							Description: "team one",
 | 
				
			||||||
 | 
							Permission:  "write",
 | 
				
			||||||
 | 
							Units:       []string{"repo.code", "repo.issues"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams?token=%s", org.Name, token), teamToCreate)
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusCreated)
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &apiTeam)
 | 
				
			||||||
 | 
						checkTeamResponse(t, &apiTeam, teamToCreate.Name, teamToCreate.Description, teamToCreate.Permission, teamToCreate.Units)
 | 
				
			||||||
 | 
						checkTeamBean(t, apiTeam.ID, teamToCreate.Name, teamToCreate.Description, teamToCreate.Permission, teamToCreate.Units)
 | 
				
			||||||
 | 
						teamID := apiTeam.ID
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Edit team.
 | 
				
			||||||
 | 
						teamToEdit := &api.EditTeamOption{
 | 
				
			||||||
 | 
							Name:        "teamone",
 | 
				
			||||||
 | 
							Description: "team 1",
 | 
				
			||||||
 | 
							Permission:  "admin",
 | 
				
			||||||
 | 
							Units:       []string{"repo.code", "repo.pulls", "repo.releases"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						req = NewRequestWithJSON(t, "PATCH", fmt.Sprintf("/api/v1/teams/%d?token=%s", teamID, token), teamToEdit)
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &apiTeam)
 | 
				
			||||||
 | 
						checkTeamResponse(t, &apiTeam, teamToEdit.Name, teamToEdit.Description, teamToEdit.Permission, teamToEdit.Units)
 | 
				
			||||||
 | 
						checkTeamBean(t, apiTeam.ID, teamToEdit.Name, teamToEdit.Description, teamToEdit.Permission, teamToEdit.Units)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Read team.
 | 
				
			||||||
 | 
						teamRead := models.AssertExistsAndLoadBean(t, &models.Team{ID: teamID}).(*models.Team)
 | 
				
			||||||
 | 
						req = NewRequestf(t, "GET", "/api/v1/teams/%d?token="+token, teamID)
 | 
				
			||||||
 | 
						resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &apiTeam)
 | 
				
			||||||
 | 
						checkTeamResponse(t, &apiTeam, teamRead.Name, teamRead.Description, teamRead.Authorize.String(), teamRead.GetUnitNames())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Delete team.
 | 
				
			||||||
 | 
						req = NewRequestf(t, "DELETE", "/api/v1/teams/%d?token="+token, teamID)
 | 
				
			||||||
 | 
						session.MakeRequest(t, req, http.StatusNoContent)
 | 
				
			||||||
 | 
						models.AssertNotExistsBean(t, &models.Team{ID: teamID})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkTeamResponse(t *testing.T, apiTeam *api.Team, name, description string, permission string, units []string) {
 | 
				
			||||||
 | 
						assert.Equal(t, name, apiTeam.Name, "name")
 | 
				
			||||||
 | 
						assert.Equal(t, description, apiTeam.Description, "description")
 | 
				
			||||||
 | 
						assert.Equal(t, permission, apiTeam.Permission, "permission")
 | 
				
			||||||
 | 
						sort.StringSlice(units).Sort()
 | 
				
			||||||
 | 
						sort.StringSlice(apiTeam.Units).Sort()
 | 
				
			||||||
 | 
						assert.EqualValues(t, units, apiTeam.Units, "units")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func checkTeamBean(t *testing.T, id int64, name, description string, permission string, units []string) {
 | 
				
			||||||
 | 
						team := models.AssertExistsAndLoadBean(t, &models.Team{ID: id}).(*models.Team)
 | 
				
			||||||
 | 
						assert.NoError(t, team.GetUnits(), "GetUnits")
 | 
				
			||||||
 | 
						checkTeamResponse(t, convert.ToTeam(team), name, description, permission, units)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										52
									
								
								integrations/api_user_search_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								integrations/api_user_search_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,52 @@
 | 
				
			|||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.package models
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						api "code.gitea.io/sdk/gitea"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SearchResults struct {
 | 
				
			||||||
 | 
						OK   bool        `json:"ok"`
 | 
				
			||||||
 | 
						Data []*api.User `json:"data"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIUserSearchLoggedIn(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						adminUsername := "user1"
 | 
				
			||||||
 | 
						session := loginUser(t, adminUsername)
 | 
				
			||||||
 | 
						token := getTokenForLoggedInUser(t, session)
 | 
				
			||||||
 | 
						query := "user2"
 | 
				
			||||||
 | 
						req := NewRequestf(t, "GET", "/api/v1/users/search?token=%s&q=%s", token, query)
 | 
				
			||||||
 | 
						resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var results SearchResults
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &results)
 | 
				
			||||||
 | 
						assert.NotEmpty(t, results.Data)
 | 
				
			||||||
 | 
						for _, user := range results.Data {
 | 
				
			||||||
 | 
							assert.Contains(t, user.UserName, query)
 | 
				
			||||||
 | 
							assert.NotEmpty(t, user.Email)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestAPIUserSearchNotLoggedIn(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
						query := "user2"
 | 
				
			||||||
 | 
						req := NewRequestf(t, "GET", "/api/v1/users/search?q=%s", query)
 | 
				
			||||||
 | 
						resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var results SearchResults
 | 
				
			||||||
 | 
						DecodeJSON(t, resp, &results)
 | 
				
			||||||
 | 
						assert.NotEmpty(t, results.Data)
 | 
				
			||||||
 | 
						for _, user := range results.Data {
 | 
				
			||||||
 | 
							assert.Contains(t, user.UserName, query)
 | 
				
			||||||
 | 
							assert.Empty(t, user.Email)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										115
									
								
								integrations/create_no_session_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								integrations/create_no_session_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,115 @@
 | 
				
			|||||||
 | 
					// Copyright 2019 The Gitea Authors. All rights reserved.
 | 
				
			||||||
 | 
					// Use of this source code is governed by a MIT-style
 | 
				
			||||||
 | 
					// license that can be found in the LICENSE file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package integrations
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"io/ioutil"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"net/http/httptest"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"path/filepath"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/modules/setting"
 | 
				
			||||||
 | 
						"code.gitea.io/gitea/routers/routes"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-macaron/session"
 | 
				
			||||||
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func getSessionID(t *testing.T, resp *httptest.ResponseRecorder) string {
 | 
				
			||||||
 | 
						cookies := resp.Result().Cookies()
 | 
				
			||||||
 | 
						found := false
 | 
				
			||||||
 | 
						sessionID := ""
 | 
				
			||||||
 | 
						for _, cookie := range cookies {
 | 
				
			||||||
 | 
							if cookie.Name == setting.SessionConfig.CookieName {
 | 
				
			||||||
 | 
								sessionID = cookie.Value
 | 
				
			||||||
 | 
								found = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						assert.True(t, found)
 | 
				
			||||||
 | 
						assert.NotEmpty(t, sessionID)
 | 
				
			||||||
 | 
						return sessionID
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sessionFile(tmpDir, sessionID string) string {
 | 
				
			||||||
 | 
						return filepath.Join(tmpDir, sessionID[0:1], sessionID[1:2], sessionID)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func sessionFileExist(t *testing.T, tmpDir, sessionID string) bool {
 | 
				
			||||||
 | 
						sessionFile := sessionFile(tmpDir, sessionID)
 | 
				
			||||||
 | 
						_, err := os.Lstat(sessionFile)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							if os.IsNotExist(err) {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							assert.NoError(t, err)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return true
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestSessionFileCreation(t *testing.T) {
 | 
				
			||||||
 | 
						prepareTestEnv(t)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						oldSessionConfig := setting.SessionConfig.ProviderConfig
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							setting.SessionConfig.ProviderConfig = oldSessionConfig
 | 
				
			||||||
 | 
							mac = routes.NewMacaron()
 | 
				
			||||||
 | 
							routes.RegisterRoutes(mac)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var config session.Options
 | 
				
			||||||
 | 
						err := json.Unmarshal([]byte(oldSessionConfig), &config)
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config.Provider = "file"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Now create a temporaryDirectory
 | 
				
			||||||
 | 
						tmpDir, err := ioutil.TempDir("", "sessions")
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if _, err := os.Stat(tmpDir); !os.IsNotExist(err) {
 | 
				
			||||||
 | 
								_ = os.RemoveAll(tmpDir)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						config.ProviderConfig = tmpDir
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						newConfigBytes, err := json.Marshal(config)
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						setting.SessionConfig.ProviderConfig = string(newConfigBytes)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mac = routes.NewMacaron()
 | 
				
			||||||
 | 
						routes.RegisterRoutes(mac)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						t.Run("NoSessionOnViewIssue", func(t *testing.T) {
 | 
				
			||||||
 | 
							req := NewRequest(t, "GET", "/user2/repo1/issues/1")
 | 
				
			||||||
 | 
							resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
							sessionID := getSessionID(t, resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// We're not logged in so there should be no session
 | 
				
			||||||
 | 
							assert.False(t, sessionFileExist(t, tmpDir, sessionID))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						t.Run("CreateSessionOnLogin", func(t *testing.T) {
 | 
				
			||||||
 | 
							req := NewRequest(t, "GET", "/user/login")
 | 
				
			||||||
 | 
							resp := MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
							sessionID := getSessionID(t, resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// We're not logged in so there should be no session
 | 
				
			||||||
 | 
							assert.False(t, sessionFileExist(t, tmpDir, sessionID))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							doc := NewHTMLParser(t, resp.Body)
 | 
				
			||||||
 | 
							req = NewRequestWithValues(t, "POST", "/user/login", map[string]string{
 | 
				
			||||||
 | 
								"_csrf":     doc.GetCSRF(),
 | 
				
			||||||
 | 
								"user_name": "user2",
 | 
				
			||||||
 | 
								"password":  userPassword,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							resp = MakeRequest(t, req, http.StatusFound)
 | 
				
			||||||
 | 
							sessionID = getSessionID(t, resp)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							assert.FileExists(t, sessionFile(tmpDir, sessionID))
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -61,6 +61,10 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
					little = commitAndPush(t, littleSize, dstPath)
 | 
										little = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Big", func(t *testing.T) {
 | 
									t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
										if testing.Short() {
 | 
				
			||||||
 | 
											t.Skip("skipping test in short mode.")
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					big = commitAndPush(t, bigSize, dstPath)
 | 
										big = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
@@ -77,9 +81,15 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
				t.Run("Little", func(t *testing.T) {
 | 
									t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
					littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
										littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
 | 
										lockFileTest(t, littleLFS, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Big", func(t *testing.T) {
 | 
									t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
										if testing.Short() {
 | 
				
			||||||
 | 
											t.Skip("skipping test in short mode.")
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
										bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
 | 
										lockFileTest(t, bigLFS, dstPath)
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("Locks", func(t *testing.T) {
 | 
								t.Run("Locks", func(t *testing.T) {
 | 
				
			||||||
@@ -94,19 +104,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
			resp := session.MakeRequest(t, req, http.StatusOK)
 | 
								resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
			assert.Equal(t, littleSize, resp.Body.Len())
 | 
								assert.Equal(t, littleSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", big))
 | 
					 | 
				
			||||||
			nilResp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
					 | 
				
			||||||
			assert.Equal(t, bigSize, nilResp.Length)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", littleLFS))
 | 
								req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", littleLFS))
 | 
				
			||||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
								resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
			assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
								assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
				
			||||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
								assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", bigLFS))
 | 
								if !testing.Short() {
 | 
				
			||||||
			resp = session.MakeRequest(t, req, http.StatusOK)
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", big))
 | 
				
			||||||
			assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
									nilResp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
				
			||||||
			assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
									assert.Equal(t, bigSize, nilResp.Length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/raw/branch/master/", bigLFS))
 | 
				
			||||||
 | 
									resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
									assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
				
			||||||
 | 
									assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
		t.Run("Media", func(t *testing.T) {
 | 
							t.Run("Media", func(t *testing.T) {
 | 
				
			||||||
@@ -117,17 +129,19 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
			resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
								resp := session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
				
			||||||
			assert.Equal(t, littleSize, resp.Length)
 | 
								assert.Equal(t, littleSize, resp.Length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", big))
 | 
					 | 
				
			||||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
					 | 
				
			||||||
			assert.Equal(t, bigSize, resp.Length)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", littleLFS))
 | 
								req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", littleLFS))
 | 
				
			||||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
								resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
				
			||||||
			assert.Equal(t, littleSize, resp.Length)
 | 
								assert.Equal(t, littleSize, resp.Length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", bigLFS))
 | 
								if !testing.Short() {
 | 
				
			||||||
			resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", big))
 | 
				
			||||||
			assert.Equal(t, bigSize, resp.Length)
 | 
									resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
				
			||||||
 | 
									assert.Equal(t, bigSize, resp.Length)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-17/media/branch/master/", bigLFS))
 | 
				
			||||||
 | 
									resp = session.MakeRequestNilResponseRecorder(t, req, http.StatusOK)
 | 
				
			||||||
 | 
									assert.Equal(t, bigSize, resp.Length)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
@@ -160,6 +174,10 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
						little = commitAndPush(t, littleSize, dstPath)
 | 
											little = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
					t.Run("Big", func(t *testing.T) {
 | 
										t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
											if testing.Short() {
 | 
				
			||||||
 | 
												t.Skip("skipping test in short mode.")
 | 
				
			||||||
 | 
												return
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
						big = commitAndPush(t, bigSize, dstPath)
 | 
											big = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
@@ -176,9 +194,16 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
					t.Run("Little", func(t *testing.T) {
 | 
										t.Run("Little", func(t *testing.T) {
 | 
				
			||||||
						littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
											littleLFS = commitAndPush(t, littleSize, dstPath)
 | 
				
			||||||
 | 
											lockFileTest(t, littleLFS, dstPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
					t.Run("Big", func(t *testing.T) {
 | 
										t.Run("Big", func(t *testing.T) {
 | 
				
			||||||
 | 
											if testing.Short() {
 | 
				
			||||||
 | 
												return
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
						bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
											bigLFS = commitAndPush(t, bigSize, dstPath)
 | 
				
			||||||
 | 
											lockFileTest(t, bigLFS, dstPath)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					})
 | 
										})
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
				t.Run("Locks", func(t *testing.T) {
 | 
									t.Run("Locks", func(t *testing.T) {
 | 
				
			||||||
@@ -193,20 +218,21 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
				resp := session.MakeRequest(t, req, http.StatusOK)
 | 
									resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
									assert.Equal(t, littleSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", big))
 | 
					 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
					 | 
				
			||||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", littleLFS))
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", littleLFS))
 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
									resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
				assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
									assert.NotEqual(t, littleSize, resp.Body.Len())
 | 
				
			||||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
									assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", bigLFS))
 | 
									if !testing.Short() {
 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
										req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", big))
 | 
				
			||||||
				assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
										resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
				assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
										assert.Equal(t, bigSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/raw/branch/master/", bigLFS))
 | 
				
			||||||
 | 
										resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
										assert.NotEqual(t, bigSize, resp.Body.Len())
 | 
				
			||||||
 | 
										assert.Contains(t, resp.Body.String(), models.LFSMetaFileIdentifier)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
			t.Run("Media", func(t *testing.T) {
 | 
								t.Run("Media", func(t *testing.T) {
 | 
				
			||||||
				session := loginUser(t, "user2")
 | 
									session := loginUser(t, "user2")
 | 
				
			||||||
@@ -216,17 +242,19 @@ func testGit(t *testing.T, u *url.URL) {
 | 
				
			|||||||
				resp := session.MakeRequest(t, req, http.StatusOK)
 | 
									resp := session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
									assert.Equal(t, littleSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", big))
 | 
					 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
					 | 
				
			||||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", littleLFS))
 | 
									req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", littleLFS))
 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
									resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
				assert.Equal(t, littleSize, resp.Body.Len())
 | 
									assert.Equal(t, littleSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
				req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", bigLFS))
 | 
									if !testing.Short() {
 | 
				
			||||||
				resp = session.MakeRequest(t, req, http.StatusOK)
 | 
										req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", big))
 | 
				
			||||||
				assert.Equal(t, bigSize, resp.Body.Len())
 | 
										resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
										assert.Equal(t, bigSize, resp.Body.Len())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
										req = NewRequest(t, "GET", path.Join("/user2/repo-tmp-18/media/branch/master/", bigLFS))
 | 
				
			||||||
 | 
										resp = session.MakeRequest(t, req, http.StatusOK)
 | 
				
			||||||
 | 
										assert.Equal(t, bigSize, resp.Body.Len())
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
			})
 | 
								})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
@@ -243,15 +271,17 @@ func ensureAnonymousClone(t *testing.T, u *url.URL) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func lockTest(t *testing.T, remote, repoPath string) {
 | 
					func lockTest(t *testing.T, remote, repoPath string) {
 | 
				
			||||||
	_, err := git.NewCommand("remote").AddArguments("set-url", "origin", remote).RunInDir(repoPath) //TODO add test ssh git-lfs-creds
 | 
						lockFileTest(t, "README.md", repoPath)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func lockFileTest(t *testing.T, filename, repoPath string) {
 | 
				
			||||||
 | 
						_, err := git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
				
			||||||
 | 
						assert.NoError(t, err)
 | 
				
			||||||
 | 
						_, err = git.NewCommand("lfs").AddArguments("lock", filename).RunInDir(repoPath)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
						_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
	_, err = git.NewCommand("lfs").AddArguments("lock", "README.md").RunInDir(repoPath)
 | 
						_, err = git.NewCommand("lfs").AddArguments("unlock", filename).RunInDir(repoPath)
 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	_, err = git.NewCommand("lfs").AddArguments("locks").RunInDir(repoPath)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
					 | 
				
			||||||
	_, err = git.NewCommand("lfs").AddArguments("unlock", "README.md").RunInDir(repoPath)
 | 
					 | 
				
			||||||
	assert.NoError(t, err)
 | 
						assert.NoError(t, err)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ref: refs/heads/master
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					[core]
 | 
				
			||||||
 | 
						repositoryformatversion = 0
 | 
				
			||||||
 | 
						filemode = true
 | 
				
			||||||
 | 
						bare = true
 | 
				
			||||||
 | 
						ignorecase = true
 | 
				
			||||||
 | 
						precomposeunicode = true
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Unnamed repository; edit this file 'description' to name the repository.
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message taken by
 | 
				
			||||||
 | 
					# applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.  The hook is
 | 
				
			||||||
 | 
					# allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "applypatch-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
 | 
				
			||||||
 | 
					test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with one argument, the name of the file
 | 
				
			||||||
 | 
					# that has the commit message.  The hook should exit with non-zero
 | 
				
			||||||
 | 
					# status after issuing an appropriate message if it wants to stop the
 | 
				
			||||||
 | 
					# commit.  The hook is allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment the below to add a Signed-off-by line to the message.
 | 
				
			||||||
 | 
					# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
 | 
				
			||||||
 | 
					# hook is more suited to it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This example catches duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "" = "$(grep '^Signed-off-by: ' "$1" |
 | 
				
			||||||
 | 
						 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
 | 
				
			||||||
 | 
						echo >&2 Duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/perl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use IPC::Open2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to integrate Watchman
 | 
				
			||||||
 | 
					# (https://facebook.github.io/watchman/) with git to speed up detecting
 | 
				
			||||||
 | 
					# new and modified files.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is passed a version (currently 1) and a time in nanoseconds
 | 
				
			||||||
 | 
					# formatted as a string and outputs to stdout all files that have been
 | 
				
			||||||
 | 
					# modified since the given time. Paths must be relative to the root of
 | 
				
			||||||
 | 
					# the working tree and separated by a single NUL.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "query-watchman" and set
 | 
				
			||||||
 | 
					# 'git config core.fsmonitor .git/hooks/query-watchman'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					my ($version, $time) = @ARGV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check the hook interface version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($version == 1) {
 | 
				
			||||||
 | 
						# convert nanoseconds to seconds
 | 
				
			||||||
 | 
						$time = int $time / 1000000000;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						die "Unsupported query-fsmonitor hook version '$version'.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $git_work_tree;
 | 
				
			||||||
 | 
					if ($^O =~ 'msys' || $^O =~ 'cygwin') {
 | 
				
			||||||
 | 
						$git_work_tree = Win32::GetCwd();
 | 
				
			||||||
 | 
						$git_work_tree =~ tr/\\/\//;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						require Cwd;
 | 
				
			||||||
 | 
						$git_work_tree = Cwd::cwd();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $retry = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					launch_watchman();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub launch_watchman {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
 | 
				
			||||||
 | 
						    or die "open2() failed: $!\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# In the query expression below we're asking for names of files that
 | 
				
			||||||
 | 
						# changed since $time but were not transient (ie created after
 | 
				
			||||||
 | 
						# $time but no longer exist).
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# To accomplish this, we're using the "since" generator to use the
 | 
				
			||||||
 | 
						# recency index to select candidate nodes and "fields" to limit the
 | 
				
			||||||
 | 
						# output to file names only. Then we're using the "expression" term to
 | 
				
			||||||
 | 
						# further constrain the results.
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# The category of transient files that we want to ignore will have a
 | 
				
			||||||
 | 
						# creation clock (cclock) newer than $time_t value and will also not
 | 
				
			||||||
 | 
						# currently exist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $query = <<"	END";
 | 
				
			||||||
 | 
							["query", "$git_work_tree", {
 | 
				
			||||||
 | 
								"since": $time,
 | 
				
			||||||
 | 
								"fields": ["name"],
 | 
				
			||||||
 | 
								"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
 | 
				
			||||||
 | 
							}]
 | 
				
			||||||
 | 
						END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print CHLD_IN $query;
 | 
				
			||||||
 | 
						close CHLD_IN;
 | 
				
			||||||
 | 
						my $response = do {local $/; <CHLD_OUT>};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: command returned no output.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $response eq "";
 | 
				
			||||||
 | 
						die "Watchman: command returned invalid output: $response\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" unless $response =~ /^\{/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $json_pkg;
 | 
				
			||||||
 | 
						eval {
 | 
				
			||||||
 | 
							require JSON::XS;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::XS";
 | 
				
			||||||
 | 
							1;
 | 
				
			||||||
 | 
						} or do {
 | 
				
			||||||
 | 
							require JSON::PP;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::PP";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $o = $json_pkg->new->utf8->decode($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
 | 
				
			||||||
 | 
							print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
 | 
				
			||||||
 | 
							$retry--;
 | 
				
			||||||
 | 
							qx/watchman watch "$git_work_tree"/;
 | 
				
			||||||
 | 
							die "Failed to make watchman watch '$git_work_tree'.\n" .
 | 
				
			||||||
 | 
							    "Falling back to scanning...\n" if $? != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Watchman will always return all files on the first query so
 | 
				
			||||||
 | 
							# return the fast "everything is dirty" flag to git and do the
 | 
				
			||||||
 | 
							# Watchman query just to get it over with now so we won't pay
 | 
				
			||||||
 | 
							# the cost in git to look up each individual file.
 | 
				
			||||||
 | 
							print "/\0";
 | 
				
			||||||
 | 
							eval { launch_watchman() };
 | 
				
			||||||
 | 
							exit 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: $o->{error}.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $o->{error};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binmode STDOUT, ":utf8";
 | 
				
			||||||
 | 
						local $, = "\0";
 | 
				
			||||||
 | 
						print @{$o->{files}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare a packed repository for use over
 | 
				
			||||||
 | 
					# dumb transports.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "post-update".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec git update-server-info
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed
 | 
				
			||||||
 | 
					# by applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-applypatch".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					precommit="$(git rev-parse --git-path hooks/pre-commit)"
 | 
				
			||||||
 | 
					test -x "$precommit" && exec "$precommit" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed.
 | 
				
			||||||
 | 
					# Called by "git commit" with no arguments.  The hook should
 | 
				
			||||||
 | 
					# exit with non-zero status after issuing an appropriate message if
 | 
				
			||||||
 | 
					# it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-commit".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if git rev-parse --verify HEAD >/dev/null 2>&1
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						against=HEAD
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						# Initial commit: diff against an empty tree object
 | 
				
			||||||
 | 
						against=$(git hash-object -t tree /dev/null)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you want to allow non-ASCII filenames set this variable to true.
 | 
				
			||||||
 | 
					allownonascii=$(git config --bool hooks.allownonascii)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Redirect output to stderr.
 | 
				
			||||||
 | 
					exec 1>&2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cross platform projects tend to avoid non-ASCII filenames; prevent
 | 
				
			||||||
 | 
					# them from being added to the repository. We exploit the fact that the
 | 
				
			||||||
 | 
					# printable range starts at the space character and ends with tilde.
 | 
				
			||||||
 | 
					if [ "$allownonascii" != "true" ] &&
 | 
				
			||||||
 | 
						# Note that the use of brackets around a tr range is ok here, (it's
 | 
				
			||||||
 | 
						# even required, for portability to Solaris 10's /usr/bin/tr), since
 | 
				
			||||||
 | 
						# the square bracket bytes happen to fall in the designated range.
 | 
				
			||||||
 | 
						test $(git diff --cached --name-only --diff-filter=A -z $against |
 | 
				
			||||||
 | 
						  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						cat <<\EOF
 | 
				
			||||||
 | 
					Error: Attempt to add a non-ASCII file name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can cause problems if you want to work with people on other platforms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To be portable it is advisable to rename the file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know what you are doing you can disable this check using:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  git config hooks.allownonascii true
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If there are whitespace errors, print the offending file names and fail.
 | 
				
			||||||
 | 
					exec git diff-index --check --cached $against --
 | 
				
			||||||
@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be pushed.  Called by "git
 | 
				
			||||||
 | 
					# push" after it has checked the remote status, but before anything has been
 | 
				
			||||||
 | 
					# pushed.  If this script exits with a non-zero status nothing will be pushed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- Name of the remote to which the push is being done
 | 
				
			||||||
 | 
					# $2 -- URL to which the push is being done
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If pushing without using a named remote those arguments will be equal.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Information about the commits which are being pushed is supplied as lines to
 | 
				
			||||||
 | 
					# the standard input in the form:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   <local ref> <local sha1> <remote ref> <remote sha1>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent push of commits where the log message starts
 | 
				
			||||||
 | 
					# with "WIP" (work in progress).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remote="$1"
 | 
				
			||||||
 | 
					url="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					z40=0000000000000000000000000000000000000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while read local_ref local_sha remote_ref remote_sha
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						if [ "$local_sha" = $z40 ]
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							# Handle delete
 | 
				
			||||||
 | 
							:
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							if [ "$remote_sha" = $z40 ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								# New branch, examine all commits
 | 
				
			||||||
 | 
								range="$local_sha"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								# Update to existing branch, examine new commits
 | 
				
			||||||
 | 
								range="$remote_sha..$local_sha"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Check for WIP commit
 | 
				
			||||||
 | 
							commit=`git rev-list -n 1 --grep '^WIP' "$range"`
 | 
				
			||||||
 | 
							if [ -n "$commit" ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo >&2 "Found WIP commit in $local_ref, not pushing"
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2006, 2008 Junio C Hamano
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The "pre-rebase" hook is run just before "git rebase" starts doing
 | 
				
			||||||
 | 
					# its job, and can prevent the command from running by exiting with
 | 
				
			||||||
 | 
					# non-zero status.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- the upstream the series was forked from.
 | 
				
			||||||
 | 
					# $2 -- the branch being rebased (or empty when rebasing the current branch).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent topic branches that are already
 | 
				
			||||||
 | 
					# merged to 'next' branch from getting rebased, because allowing it
 | 
				
			||||||
 | 
					# would result in rebasing already published history.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish=next
 | 
				
			||||||
 | 
					basebranch="$1"
 | 
				
			||||||
 | 
					if test "$#" = 2
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						topic="refs/heads/$2"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						topic=`git symbolic-ref HEAD` ||
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt rebasing detached HEAD
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$topic" in
 | 
				
			||||||
 | 
					refs/heads/??/*)
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					*)
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt others.
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Now we are dealing with a topic branch being rebased
 | 
				
			||||||
 | 
					# on top of master.  Is it OK to rebase it?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Does the topic really exist?
 | 
				
			||||||
 | 
					git show-ref -q "$topic" || {
 | 
				
			||||||
 | 
						echo >&2 "No such branch $topic"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic fully merged to master?
 | 
				
			||||||
 | 
					not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
 | 
				
			||||||
 | 
					if test -z "$not_in_master"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						echo >&2 "$topic is fully merged to master; better remove it."
 | 
				
			||||||
 | 
						exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic ever merged to next?  If so you should not be rebasing it.
 | 
				
			||||||
 | 
					only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
 | 
				
			||||||
 | 
					only_next_2=`git rev-list ^master           ${publish} | sort`
 | 
				
			||||||
 | 
					if test "$only_next_1" = "$only_next_2"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						not_in_topic=`git rev-list "^$topic" master`
 | 
				
			||||||
 | 
						if test -z "$not_in_topic"
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							echo >&2 "$topic is already up to date with master"
 | 
				
			||||||
 | 
							exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
 | 
				
			||||||
 | 
						/usr/bin/perl -e '
 | 
				
			||||||
 | 
							my $topic = $ARGV[0];
 | 
				
			||||||
 | 
							my $msg = "* $topic has commits already merged to public branch:\n";
 | 
				
			||||||
 | 
							my (%not_in_next) = map {
 | 
				
			||||||
 | 
								/^([0-9a-f]+) /;
 | 
				
			||||||
 | 
								($1 => 1);
 | 
				
			||||||
 | 
							} split(/\n/, $ARGV[1]);
 | 
				
			||||||
 | 
							for my $elem (map {
 | 
				
			||||||
 | 
									/^([0-9a-f]+) (.*)$/;
 | 
				
			||||||
 | 
									[$1 => $2];
 | 
				
			||||||
 | 
								} split(/\n/, $ARGV[2])) {
 | 
				
			||||||
 | 
								if (!exists $not_in_next{$elem->[0]}) {
 | 
				
			||||||
 | 
									if ($msg) {
 | 
				
			||||||
 | 
										print STDERR $msg;
 | 
				
			||||||
 | 
										undef $msg;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									print STDERR " $elem->[1]\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						' "$topic" "$not_in_next" "$not_in_master"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<\DOC_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This sample hook safeguards topic branches that have been
 | 
				
			||||||
 | 
					published from being rewound.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The workflow assumed here is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch forks from "master", "master" is never
 | 
				
			||||||
 | 
					   merged into it again (either directly or indirectly).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch is fully cooked and merged into "master",
 | 
				
			||||||
 | 
					   it is deleted.  If you need to build on top of it to correct
 | 
				
			||||||
 | 
					   earlier mistakes, a new topic branch is created by forking at
 | 
				
			||||||
 | 
					   the tip of the "master".  This is not strictly necessary, but
 | 
				
			||||||
 | 
					   it makes it easier to keep your history simple.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Whenever you need to test or publish your changes to topic
 | 
				
			||||||
 | 
					   branches, merge them into "next" branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The script, being an example, hardcodes the publish branch name
 | 
				
			||||||
 | 
					to be "next", but it is trivial to make it configurable via
 | 
				
			||||||
 | 
					$GIT_DIR/config mechanism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With this workflow, you would want to know:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(1) ... if a topic branch has ever been merged to "next".  Young
 | 
				
			||||||
 | 
					    topic branches can have stupid mistakes you would rather
 | 
				
			||||||
 | 
					    clean up before publishing, and things that have not been
 | 
				
			||||||
 | 
					    merged into other branches can be easily rebased without
 | 
				
			||||||
 | 
					    affecting other people.  But once it is published, you would
 | 
				
			||||||
 | 
					    not want to rewind it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(2) ... if a topic branch has been fully merged to "master".
 | 
				
			||||||
 | 
					    Then you can delete it.  More importantly, you should not
 | 
				
			||||||
 | 
					    build on top of it -- other people may already want to
 | 
				
			||||||
 | 
					    change things related to the topic as patches against your
 | 
				
			||||||
 | 
					    "master", so if you need further changes, it is better to
 | 
				
			||||||
 | 
					    fork the topic (perhaps with the same name) afresh from the
 | 
				
			||||||
 | 
					    tip of "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's look at this example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							   o---o---o---o---o---o---o---o---o---o "next"
 | 
				
			||||||
 | 
							  /       /           /           /
 | 
				
			||||||
 | 
							 /   a---a---b A     /           /
 | 
				
			||||||
 | 
							/   /               /           /
 | 
				
			||||||
 | 
						       /   /   c---c---c---c B         /
 | 
				
			||||||
 | 
						      /   /   /             \         /
 | 
				
			||||||
 | 
						     /   /   /   b---b C     \       /
 | 
				
			||||||
 | 
						    /   /   /   /             \     /
 | 
				
			||||||
 | 
					    ---o---o---o---o---o---o---o---o---o---o---o "master"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A, B and C are topic branches.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * A has one fix since it was merged up to "next".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * B has finished.  It has been fully merged up to "master" and "next",
 | 
				
			||||||
 | 
					   and is ready to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * C has not merged to "next" at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We would want to allow C to be rebased, refuse A, and encourage
 | 
				
			||||||
 | 
					B to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list ^master ^topic next
 | 
				
			||||||
 | 
						git rev-list ^master        next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if these match, topic has not merged in next at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (2):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list master..topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if this is empty, it is fully merged to "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DOC_END
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to make use of push options.
 | 
				
			||||||
 | 
					# The example simply echoes all push options that start with 'echoback='
 | 
				
			||||||
 | 
					# and rejects all pushes when the "reject" push option is used.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-receive".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						i=0
 | 
				
			||||||
 | 
						while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
						do
 | 
				
			||||||
 | 
							eval "value=\$GIT_PUSH_OPTION_$i"
 | 
				
			||||||
 | 
							case "$value" in
 | 
				
			||||||
 | 
							echoback=*)
 | 
				
			||||||
 | 
								echo "echo from the pre-receive-hook: ${value#*=}" >&2
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							reject)
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							i=$((i + 1))
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with the name of the file that has the
 | 
				
			||||||
 | 
					# commit message, followed by the description of the commit
 | 
				
			||||||
 | 
					# message's source.  The hook's purpose is to edit the commit
 | 
				
			||||||
 | 
					# message file.  If the hook fails with a non-zero status,
 | 
				
			||||||
 | 
					# the commit is aborted.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "prepare-commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This hook includes three examples. The first one removes the
 | 
				
			||||||
 | 
					# "# Please enter the commit message..." help message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The second includes the output of "git diff --name-status -r"
 | 
				
			||||||
 | 
					# into the message, just before the "git status" output.  It is
 | 
				
			||||||
 | 
					# commented because it doesn't cope with --amend or with squashed
 | 
				
			||||||
 | 
					# commits.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The third example adds a Signed-off-by line to the message, that can
 | 
				
			||||||
 | 
					# still be edited.  This is rarely a good idea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT_MSG_FILE=$1
 | 
				
			||||||
 | 
					COMMIT_SOURCE=$2
 | 
				
			||||||
 | 
					SHA1=$3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# case "$COMMIT_SOURCE,$SHA1" in
 | 
				
			||||||
 | 
					#  ,|template,)
 | 
				
			||||||
 | 
					#    /usr/bin/perl -i.bak -pe '
 | 
				
			||||||
 | 
					#       print "\n" . `git diff --cached --name-status -r`
 | 
				
			||||||
 | 
					# 	 if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
 | 
				
			||||||
 | 
					#  *) ;;
 | 
				
			||||||
 | 
					# esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# if test -z "$COMMIT_SOURCE"
 | 
				
			||||||
 | 
					# then
 | 
				
			||||||
 | 
					#   /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# fi
 | 
				
			||||||
@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to block unannotated tags from entering.
 | 
				
			||||||
 | 
					# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "update".
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Config
 | 
				
			||||||
 | 
					# ------
 | 
				
			||||||
 | 
					# hooks.allowunannotated
 | 
				
			||||||
 | 
					#   This boolean sets whether unannotated tags will be allowed into the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletetag
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting tags will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowmodifytag
 | 
				
			||||||
 | 
					#   This boolean sets whether a tag may be modified after creation. By default
 | 
				
			||||||
 | 
					#   it won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting branches will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.denycreatebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether remotely creating branches will be denied
 | 
				
			||||||
 | 
					#   in the repository.  By default this is allowed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Command line
 | 
				
			||||||
 | 
					refname="$1"
 | 
				
			||||||
 | 
					oldrev="$2"
 | 
				
			||||||
 | 
					newrev="$3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Safety check
 | 
				
			||||||
 | 
					if [ -z "$GIT_DIR" ]; then
 | 
				
			||||||
 | 
						echo "Don't run this script from the command line." >&2
 | 
				
			||||||
 | 
						echo " (if you want, you could supply GIT_DIR then run" >&2
 | 
				
			||||||
 | 
						echo "  $0 <ref> <oldrev> <newrev>)" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
 | 
				
			||||||
 | 
						echo "usage: $0 <ref> <oldrev> <newrev>" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Config
 | 
				
			||||||
 | 
					allowunannotated=$(git config --bool hooks.allowunannotated)
 | 
				
			||||||
 | 
					allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
 | 
				
			||||||
 | 
					denycreatebranch=$(git config --bool hooks.denycreatebranch)
 | 
				
			||||||
 | 
					allowdeletetag=$(git config --bool hooks.allowdeletetag)
 | 
				
			||||||
 | 
					allowmodifytag=$(git config --bool hooks.allowmodifytag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for no description
 | 
				
			||||||
 | 
					projectdesc=$(sed -e '1q' "$GIT_DIR/description")
 | 
				
			||||||
 | 
					case "$projectdesc" in
 | 
				
			||||||
 | 
					"Unnamed repository"* | "")
 | 
				
			||||||
 | 
						echo "*** Project description file hasn't been set" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Check types
 | 
				
			||||||
 | 
					# if $newrev is 0000...0000, it's a commit to delete a ref.
 | 
				
			||||||
 | 
					zero="0000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					if [ "$newrev" = "$zero" ]; then
 | 
				
			||||||
 | 
						newrev_type=delete
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						newrev_type=$(git cat-file -t $newrev)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$refname","$newrev_type" in
 | 
				
			||||||
 | 
						refs/tags/*,commit)
 | 
				
			||||||
 | 
							# un-annotated tag
 | 
				
			||||||
 | 
							short_refname=${refname##refs/tags/}
 | 
				
			||||||
 | 
							if [ "$allowunannotated" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,delete)
 | 
				
			||||||
 | 
							# delete tag
 | 
				
			||||||
 | 
							if [ "$allowdeletetag" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tag is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,tag)
 | 
				
			||||||
 | 
							# annotated tag
 | 
				
			||||||
 | 
							if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo "*** Tag '$refname' already exists." >&2
 | 
				
			||||||
 | 
								echo "*** Modifying a tag is not allowed in this repository." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,commit)
 | 
				
			||||||
 | 
							# branch
 | 
				
			||||||
 | 
							if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Creating a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,delete)
 | 
				
			||||||
 | 
							# delete branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,commit)
 | 
				
			||||||
 | 
							# tracking branch
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,delete)
 | 
				
			||||||
 | 
							# delete tracking branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tracking branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						*)
 | 
				
			||||||
 | 
							# Anything else (is there anything else?)
 | 
				
			||||||
 | 
							echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Finished
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# git ls-files --others --exclude-from=.git/info/exclude
 | 
				
			||||||
 | 
					# Lines that start with '#' are comments.
 | 
				
			||||||
 | 
					# For a project mostly in C, the following would be a good set of
 | 
				
			||||||
 | 
					# exclude patterns (uncomment them if you want to use them):
 | 
				
			||||||
 | 
					# *.[oa]
 | 
				
			||||||
 | 
					# *~
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					b895782bd271fdd266dd06e5880ea4abdc3a0dc7
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ref: refs/heads/master
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					[core]
 | 
				
			||||||
 | 
						repositoryformatversion = 0
 | 
				
			||||||
 | 
						filemode = true
 | 
				
			||||||
 | 
						bare = true
 | 
				
			||||||
 | 
						ignorecase = true
 | 
				
			||||||
 | 
						precomposeunicode = true
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Unnamed repository; edit this file 'description' to name the repository.
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message taken by
 | 
				
			||||||
 | 
					# applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.  The hook is
 | 
				
			||||||
 | 
					# allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "applypatch-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
 | 
				
			||||||
 | 
					test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with one argument, the name of the file
 | 
				
			||||||
 | 
					# that has the commit message.  The hook should exit with non-zero
 | 
				
			||||||
 | 
					# status after issuing an appropriate message if it wants to stop the
 | 
				
			||||||
 | 
					# commit.  The hook is allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment the below to add a Signed-off-by line to the message.
 | 
				
			||||||
 | 
					# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
 | 
				
			||||||
 | 
					# hook is more suited to it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This example catches duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "" = "$(grep '^Signed-off-by: ' "$1" |
 | 
				
			||||||
 | 
						 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
 | 
				
			||||||
 | 
						echo >&2 Duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/perl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use IPC::Open2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to integrate Watchman
 | 
				
			||||||
 | 
					# (https://facebook.github.io/watchman/) with git to speed up detecting
 | 
				
			||||||
 | 
					# new and modified files.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is passed a version (currently 1) and a time in nanoseconds
 | 
				
			||||||
 | 
					# formatted as a string and outputs to stdout all files that have been
 | 
				
			||||||
 | 
					# modified since the given time. Paths must be relative to the root of
 | 
				
			||||||
 | 
					# the working tree and separated by a single NUL.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "query-watchman" and set
 | 
				
			||||||
 | 
					# 'git config core.fsmonitor .git/hooks/query-watchman'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					my ($version, $time) = @ARGV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check the hook interface version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($version == 1) {
 | 
				
			||||||
 | 
						# convert nanoseconds to seconds
 | 
				
			||||||
 | 
						$time = int $time / 1000000000;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						die "Unsupported query-fsmonitor hook version '$version'.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $git_work_tree;
 | 
				
			||||||
 | 
					if ($^O =~ 'msys' || $^O =~ 'cygwin') {
 | 
				
			||||||
 | 
						$git_work_tree = Win32::GetCwd();
 | 
				
			||||||
 | 
						$git_work_tree =~ tr/\\/\//;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						require Cwd;
 | 
				
			||||||
 | 
						$git_work_tree = Cwd::cwd();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $retry = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					launch_watchman();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub launch_watchman {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
 | 
				
			||||||
 | 
						    or die "open2() failed: $!\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# In the query expression below we're asking for names of files that
 | 
				
			||||||
 | 
						# changed since $time but were not transient (ie created after
 | 
				
			||||||
 | 
						# $time but no longer exist).
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# To accomplish this, we're using the "since" generator to use the
 | 
				
			||||||
 | 
						# recency index to select candidate nodes and "fields" to limit the
 | 
				
			||||||
 | 
						# output to file names only. Then we're using the "expression" term to
 | 
				
			||||||
 | 
						# further constrain the results.
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# The category of transient files that we want to ignore will have a
 | 
				
			||||||
 | 
						# creation clock (cclock) newer than $time_t value and will also not
 | 
				
			||||||
 | 
						# currently exist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $query = <<"	END";
 | 
				
			||||||
 | 
							["query", "$git_work_tree", {
 | 
				
			||||||
 | 
								"since": $time,
 | 
				
			||||||
 | 
								"fields": ["name"],
 | 
				
			||||||
 | 
								"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
 | 
				
			||||||
 | 
							}]
 | 
				
			||||||
 | 
						END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print CHLD_IN $query;
 | 
				
			||||||
 | 
						close CHLD_IN;
 | 
				
			||||||
 | 
						my $response = do {local $/; <CHLD_OUT>};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: command returned no output.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $response eq "";
 | 
				
			||||||
 | 
						die "Watchman: command returned invalid output: $response\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" unless $response =~ /^\{/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $json_pkg;
 | 
				
			||||||
 | 
						eval {
 | 
				
			||||||
 | 
							require JSON::XS;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::XS";
 | 
				
			||||||
 | 
							1;
 | 
				
			||||||
 | 
						} or do {
 | 
				
			||||||
 | 
							require JSON::PP;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::PP";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $o = $json_pkg->new->utf8->decode($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
 | 
				
			||||||
 | 
							print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
 | 
				
			||||||
 | 
							$retry--;
 | 
				
			||||||
 | 
							qx/watchman watch "$git_work_tree"/;
 | 
				
			||||||
 | 
							die "Failed to make watchman watch '$git_work_tree'.\n" .
 | 
				
			||||||
 | 
							    "Falling back to scanning...\n" if $? != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Watchman will always return all files on the first query so
 | 
				
			||||||
 | 
							# return the fast "everything is dirty" flag to git and do the
 | 
				
			||||||
 | 
							# Watchman query just to get it over with now so we won't pay
 | 
				
			||||||
 | 
							# the cost in git to look up each individual file.
 | 
				
			||||||
 | 
							print "/\0";
 | 
				
			||||||
 | 
							eval { launch_watchman() };
 | 
				
			||||||
 | 
							exit 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: $o->{error}.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $o->{error};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binmode STDOUT, ":utf8";
 | 
				
			||||||
 | 
						local $, = "\0";
 | 
				
			||||||
 | 
						print @{$o->{files}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare a packed repository for use over
 | 
				
			||||||
 | 
					# dumb transports.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "post-update".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec git update-server-info
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed
 | 
				
			||||||
 | 
					# by applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-applypatch".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					precommit="$(git rev-parse --git-path hooks/pre-commit)"
 | 
				
			||||||
 | 
					test -x "$precommit" && exec "$precommit" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed.
 | 
				
			||||||
 | 
					# Called by "git commit" with no arguments.  The hook should
 | 
				
			||||||
 | 
					# exit with non-zero status after issuing an appropriate message if
 | 
				
			||||||
 | 
					# it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-commit".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if git rev-parse --verify HEAD >/dev/null 2>&1
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						against=HEAD
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						# Initial commit: diff against an empty tree object
 | 
				
			||||||
 | 
						against=$(git hash-object -t tree /dev/null)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you want to allow non-ASCII filenames set this variable to true.
 | 
				
			||||||
 | 
					allownonascii=$(git config --bool hooks.allownonascii)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Redirect output to stderr.
 | 
				
			||||||
 | 
					exec 1>&2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cross platform projects tend to avoid non-ASCII filenames; prevent
 | 
				
			||||||
 | 
					# them from being added to the repository. We exploit the fact that the
 | 
				
			||||||
 | 
					# printable range starts at the space character and ends with tilde.
 | 
				
			||||||
 | 
					if [ "$allownonascii" != "true" ] &&
 | 
				
			||||||
 | 
						# Note that the use of brackets around a tr range is ok here, (it's
 | 
				
			||||||
 | 
						# even required, for portability to Solaris 10's /usr/bin/tr), since
 | 
				
			||||||
 | 
						# the square bracket bytes happen to fall in the designated range.
 | 
				
			||||||
 | 
						test $(git diff --cached --name-only --diff-filter=A -z $against |
 | 
				
			||||||
 | 
						  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						cat <<\EOF
 | 
				
			||||||
 | 
					Error: Attempt to add a non-ASCII file name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can cause problems if you want to work with people on other platforms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To be portable it is advisable to rename the file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know what you are doing you can disable this check using:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  git config hooks.allownonascii true
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If there are whitespace errors, print the offending file names and fail.
 | 
				
			||||||
 | 
					exec git diff-index --check --cached $against --
 | 
				
			||||||
@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be pushed.  Called by "git
 | 
				
			||||||
 | 
					# push" after it has checked the remote status, but before anything has been
 | 
				
			||||||
 | 
					# pushed.  If this script exits with a non-zero status nothing will be pushed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- Name of the remote to which the push is being done
 | 
				
			||||||
 | 
					# $2 -- URL to which the push is being done
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If pushing without using a named remote those arguments will be equal.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Information about the commits which are being pushed is supplied as lines to
 | 
				
			||||||
 | 
					# the standard input in the form:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   <local ref> <local sha1> <remote ref> <remote sha1>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent push of commits where the log message starts
 | 
				
			||||||
 | 
					# with "WIP" (work in progress).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remote="$1"
 | 
				
			||||||
 | 
					url="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					z40=0000000000000000000000000000000000000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while read local_ref local_sha remote_ref remote_sha
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						if [ "$local_sha" = $z40 ]
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							# Handle delete
 | 
				
			||||||
 | 
							:
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							if [ "$remote_sha" = $z40 ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								# New branch, examine all commits
 | 
				
			||||||
 | 
								range="$local_sha"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								# Update to existing branch, examine new commits
 | 
				
			||||||
 | 
								range="$remote_sha..$local_sha"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Check for WIP commit
 | 
				
			||||||
 | 
							commit=`git rev-list -n 1 --grep '^WIP' "$range"`
 | 
				
			||||||
 | 
							if [ -n "$commit" ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo >&2 "Found WIP commit in $local_ref, not pushing"
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2006, 2008 Junio C Hamano
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The "pre-rebase" hook is run just before "git rebase" starts doing
 | 
				
			||||||
 | 
					# its job, and can prevent the command from running by exiting with
 | 
				
			||||||
 | 
					# non-zero status.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- the upstream the series was forked from.
 | 
				
			||||||
 | 
					# $2 -- the branch being rebased (or empty when rebasing the current branch).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent topic branches that are already
 | 
				
			||||||
 | 
					# merged to 'next' branch from getting rebased, because allowing it
 | 
				
			||||||
 | 
					# would result in rebasing already published history.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish=next
 | 
				
			||||||
 | 
					basebranch="$1"
 | 
				
			||||||
 | 
					if test "$#" = 2
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						topic="refs/heads/$2"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						topic=`git symbolic-ref HEAD` ||
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt rebasing detached HEAD
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$topic" in
 | 
				
			||||||
 | 
					refs/heads/??/*)
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					*)
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt others.
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Now we are dealing with a topic branch being rebased
 | 
				
			||||||
 | 
					# on top of master.  Is it OK to rebase it?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Does the topic really exist?
 | 
				
			||||||
 | 
					git show-ref -q "$topic" || {
 | 
				
			||||||
 | 
						echo >&2 "No such branch $topic"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic fully merged to master?
 | 
				
			||||||
 | 
					not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
 | 
				
			||||||
 | 
					if test -z "$not_in_master"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						echo >&2 "$topic is fully merged to master; better remove it."
 | 
				
			||||||
 | 
						exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic ever merged to next?  If so you should not be rebasing it.
 | 
				
			||||||
 | 
					only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
 | 
				
			||||||
 | 
					only_next_2=`git rev-list ^master           ${publish} | sort`
 | 
				
			||||||
 | 
					if test "$only_next_1" = "$only_next_2"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						not_in_topic=`git rev-list "^$topic" master`
 | 
				
			||||||
 | 
						if test -z "$not_in_topic"
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							echo >&2 "$topic is already up to date with master"
 | 
				
			||||||
 | 
							exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
 | 
				
			||||||
 | 
						/usr/bin/perl -e '
 | 
				
			||||||
 | 
							my $topic = $ARGV[0];
 | 
				
			||||||
 | 
							my $msg = "* $topic has commits already merged to public branch:\n";
 | 
				
			||||||
 | 
							my (%not_in_next) = map {
 | 
				
			||||||
 | 
								/^([0-9a-f]+) /;
 | 
				
			||||||
 | 
								($1 => 1);
 | 
				
			||||||
 | 
							} split(/\n/, $ARGV[1]);
 | 
				
			||||||
 | 
							for my $elem (map {
 | 
				
			||||||
 | 
									/^([0-9a-f]+) (.*)$/;
 | 
				
			||||||
 | 
									[$1 => $2];
 | 
				
			||||||
 | 
								} split(/\n/, $ARGV[2])) {
 | 
				
			||||||
 | 
								if (!exists $not_in_next{$elem->[0]}) {
 | 
				
			||||||
 | 
									if ($msg) {
 | 
				
			||||||
 | 
										print STDERR $msg;
 | 
				
			||||||
 | 
										undef $msg;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									print STDERR " $elem->[1]\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						' "$topic" "$not_in_next" "$not_in_master"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<\DOC_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This sample hook safeguards topic branches that have been
 | 
				
			||||||
 | 
					published from being rewound.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The workflow assumed here is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch forks from "master", "master" is never
 | 
				
			||||||
 | 
					   merged into it again (either directly or indirectly).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch is fully cooked and merged into "master",
 | 
				
			||||||
 | 
					   it is deleted.  If you need to build on top of it to correct
 | 
				
			||||||
 | 
					   earlier mistakes, a new topic branch is created by forking at
 | 
				
			||||||
 | 
					   the tip of the "master".  This is not strictly necessary, but
 | 
				
			||||||
 | 
					   it makes it easier to keep your history simple.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Whenever you need to test or publish your changes to topic
 | 
				
			||||||
 | 
					   branches, merge them into "next" branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The script, being an example, hardcodes the publish branch name
 | 
				
			||||||
 | 
					to be "next", but it is trivial to make it configurable via
 | 
				
			||||||
 | 
					$GIT_DIR/config mechanism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With this workflow, you would want to know:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(1) ... if a topic branch has ever been merged to "next".  Young
 | 
				
			||||||
 | 
					    topic branches can have stupid mistakes you would rather
 | 
				
			||||||
 | 
					    clean up before publishing, and things that have not been
 | 
				
			||||||
 | 
					    merged into other branches can be easily rebased without
 | 
				
			||||||
 | 
					    affecting other people.  But once it is published, you would
 | 
				
			||||||
 | 
					    not want to rewind it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(2) ... if a topic branch has been fully merged to "master".
 | 
				
			||||||
 | 
					    Then you can delete it.  More importantly, you should not
 | 
				
			||||||
 | 
					    build on top of it -- other people may already want to
 | 
				
			||||||
 | 
					    change things related to the topic as patches against your
 | 
				
			||||||
 | 
					    "master", so if you need further changes, it is better to
 | 
				
			||||||
 | 
					    fork the topic (perhaps with the same name) afresh from the
 | 
				
			||||||
 | 
					    tip of "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's look at this example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							   o---o---o---o---o---o---o---o---o---o "next"
 | 
				
			||||||
 | 
							  /       /           /           /
 | 
				
			||||||
 | 
							 /   a---a---b A     /           /
 | 
				
			||||||
 | 
							/   /               /           /
 | 
				
			||||||
 | 
						       /   /   c---c---c---c B         /
 | 
				
			||||||
 | 
						      /   /   /             \         /
 | 
				
			||||||
 | 
						     /   /   /   b---b C     \       /
 | 
				
			||||||
 | 
						    /   /   /   /             \     /
 | 
				
			||||||
 | 
					    ---o---o---o---o---o---o---o---o---o---o---o "master"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A, B and C are topic branches.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * A has one fix since it was merged up to "next".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * B has finished.  It has been fully merged up to "master" and "next",
 | 
				
			||||||
 | 
					   and is ready to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * C has not merged to "next" at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We would want to allow C to be rebased, refuse A, and encourage
 | 
				
			||||||
 | 
					B to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list ^master ^topic next
 | 
				
			||||||
 | 
						git rev-list ^master        next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if these match, topic has not merged in next at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (2):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list master..topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if this is empty, it is fully merged to "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DOC_END
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to make use of push options.
 | 
				
			||||||
 | 
					# The example simply echoes all push options that start with 'echoback='
 | 
				
			||||||
 | 
					# and rejects all pushes when the "reject" push option is used.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-receive".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						i=0
 | 
				
			||||||
 | 
						while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
						do
 | 
				
			||||||
 | 
							eval "value=\$GIT_PUSH_OPTION_$i"
 | 
				
			||||||
 | 
							case "$value" in
 | 
				
			||||||
 | 
							echoback=*)
 | 
				
			||||||
 | 
								echo "echo from the pre-receive-hook: ${value#*=}" >&2
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							reject)
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							i=$((i + 1))
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with the name of the file that has the
 | 
				
			||||||
 | 
					# commit message, followed by the description of the commit
 | 
				
			||||||
 | 
					# message's source.  The hook's purpose is to edit the commit
 | 
				
			||||||
 | 
					# message file.  If the hook fails with a non-zero status,
 | 
				
			||||||
 | 
					# the commit is aborted.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "prepare-commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This hook includes three examples. The first one removes the
 | 
				
			||||||
 | 
					# "# Please enter the commit message..." help message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The second includes the output of "git diff --name-status -r"
 | 
				
			||||||
 | 
					# into the message, just before the "git status" output.  It is
 | 
				
			||||||
 | 
					# commented because it doesn't cope with --amend or with squashed
 | 
				
			||||||
 | 
					# commits.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The third example adds a Signed-off-by line to the message, that can
 | 
				
			||||||
 | 
					# still be edited.  This is rarely a good idea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT_MSG_FILE=$1
 | 
				
			||||||
 | 
					COMMIT_SOURCE=$2
 | 
				
			||||||
 | 
					SHA1=$3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# case "$COMMIT_SOURCE,$SHA1" in
 | 
				
			||||||
 | 
					#  ,|template,)
 | 
				
			||||||
 | 
					#    /usr/bin/perl -i.bak -pe '
 | 
				
			||||||
 | 
					#       print "\n" . `git diff --cached --name-status -r`
 | 
				
			||||||
 | 
					# 	 if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
 | 
				
			||||||
 | 
					#  *) ;;
 | 
				
			||||||
 | 
					# esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# if test -z "$COMMIT_SOURCE"
 | 
				
			||||||
 | 
					# then
 | 
				
			||||||
 | 
					#   /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# fi
 | 
				
			||||||
@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to block unannotated tags from entering.
 | 
				
			||||||
 | 
					# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "update".
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Config
 | 
				
			||||||
 | 
					# ------
 | 
				
			||||||
 | 
					# hooks.allowunannotated
 | 
				
			||||||
 | 
					#   This boolean sets whether unannotated tags will be allowed into the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletetag
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting tags will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowmodifytag
 | 
				
			||||||
 | 
					#   This boolean sets whether a tag may be modified after creation. By default
 | 
				
			||||||
 | 
					#   it won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting branches will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.denycreatebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether remotely creating branches will be denied
 | 
				
			||||||
 | 
					#   in the repository.  By default this is allowed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Command line
 | 
				
			||||||
 | 
					refname="$1"
 | 
				
			||||||
 | 
					oldrev="$2"
 | 
				
			||||||
 | 
					newrev="$3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Safety check
 | 
				
			||||||
 | 
					if [ -z "$GIT_DIR" ]; then
 | 
				
			||||||
 | 
						echo "Don't run this script from the command line." >&2
 | 
				
			||||||
 | 
						echo " (if you want, you could supply GIT_DIR then run" >&2
 | 
				
			||||||
 | 
						echo "  $0 <ref> <oldrev> <newrev>)" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
 | 
				
			||||||
 | 
						echo "usage: $0 <ref> <oldrev> <newrev>" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Config
 | 
				
			||||||
 | 
					allowunannotated=$(git config --bool hooks.allowunannotated)
 | 
				
			||||||
 | 
					allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
 | 
				
			||||||
 | 
					denycreatebranch=$(git config --bool hooks.denycreatebranch)
 | 
				
			||||||
 | 
					allowdeletetag=$(git config --bool hooks.allowdeletetag)
 | 
				
			||||||
 | 
					allowmodifytag=$(git config --bool hooks.allowmodifytag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for no description
 | 
				
			||||||
 | 
					projectdesc=$(sed -e '1q' "$GIT_DIR/description")
 | 
				
			||||||
 | 
					case "$projectdesc" in
 | 
				
			||||||
 | 
					"Unnamed repository"* | "")
 | 
				
			||||||
 | 
						echo "*** Project description file hasn't been set" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Check types
 | 
				
			||||||
 | 
					# if $newrev is 0000...0000, it's a commit to delete a ref.
 | 
				
			||||||
 | 
					zero="0000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					if [ "$newrev" = "$zero" ]; then
 | 
				
			||||||
 | 
						newrev_type=delete
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						newrev_type=$(git cat-file -t $newrev)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$refname","$newrev_type" in
 | 
				
			||||||
 | 
						refs/tags/*,commit)
 | 
				
			||||||
 | 
							# un-annotated tag
 | 
				
			||||||
 | 
							short_refname=${refname##refs/tags/}
 | 
				
			||||||
 | 
							if [ "$allowunannotated" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,delete)
 | 
				
			||||||
 | 
							# delete tag
 | 
				
			||||||
 | 
							if [ "$allowdeletetag" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tag is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,tag)
 | 
				
			||||||
 | 
							# annotated tag
 | 
				
			||||||
 | 
							if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo "*** Tag '$refname' already exists." >&2
 | 
				
			||||||
 | 
								echo "*** Modifying a tag is not allowed in this repository." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,commit)
 | 
				
			||||||
 | 
							# branch
 | 
				
			||||||
 | 
							if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Creating a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,delete)
 | 
				
			||||||
 | 
							# delete branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,commit)
 | 
				
			||||||
 | 
							# tracking branch
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,delete)
 | 
				
			||||||
 | 
							# delete tracking branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tracking branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						*)
 | 
				
			||||||
 | 
							# Anything else (is there anything else?)
 | 
				
			||||||
 | 
							echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Finished
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# git ls-files --others --exclude-from=.git/info/exclude
 | 
				
			||||||
 | 
					# Lines that start with '#' are comments.
 | 
				
			||||||
 | 
					# For a project mostly in C, the following would be a good set of
 | 
				
			||||||
 | 
					# exclude patterns (uncomment them if you want to use them):
 | 
				
			||||||
 | 
					# *.[oa]
 | 
				
			||||||
 | 
					# *~
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					90e402c3937a4639725fcc59ca1f529e7dc8506f
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ref: refs/heads/master
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					[core]
 | 
				
			||||||
 | 
						repositoryformatversion = 0
 | 
				
			||||||
 | 
						filemode = true
 | 
				
			||||||
 | 
						bare = true
 | 
				
			||||||
 | 
						ignorecase = true
 | 
				
			||||||
 | 
						precomposeunicode = true
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Unnamed repository; edit this file 'description' to name the repository.
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message taken by
 | 
				
			||||||
 | 
					# applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.  The hook is
 | 
				
			||||||
 | 
					# allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "applypatch-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
 | 
				
			||||||
 | 
					test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with one argument, the name of the file
 | 
				
			||||||
 | 
					# that has the commit message.  The hook should exit with non-zero
 | 
				
			||||||
 | 
					# status after issuing an appropriate message if it wants to stop the
 | 
				
			||||||
 | 
					# commit.  The hook is allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment the below to add a Signed-off-by line to the message.
 | 
				
			||||||
 | 
					# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
 | 
				
			||||||
 | 
					# hook is more suited to it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This example catches duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "" = "$(grep '^Signed-off-by: ' "$1" |
 | 
				
			||||||
 | 
						 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
 | 
				
			||||||
 | 
						echo >&2 Duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/perl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use IPC::Open2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to integrate Watchman
 | 
				
			||||||
 | 
					# (https://facebook.github.io/watchman/) with git to speed up detecting
 | 
				
			||||||
 | 
					# new and modified files.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is passed a version (currently 1) and a time in nanoseconds
 | 
				
			||||||
 | 
					# formatted as a string and outputs to stdout all files that have been
 | 
				
			||||||
 | 
					# modified since the given time. Paths must be relative to the root of
 | 
				
			||||||
 | 
					# the working tree and separated by a single NUL.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "query-watchman" and set
 | 
				
			||||||
 | 
					# 'git config core.fsmonitor .git/hooks/query-watchman'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					my ($version, $time) = @ARGV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check the hook interface version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($version == 1) {
 | 
				
			||||||
 | 
						# convert nanoseconds to seconds
 | 
				
			||||||
 | 
						$time = int $time / 1000000000;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						die "Unsupported query-fsmonitor hook version '$version'.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $git_work_tree;
 | 
				
			||||||
 | 
					if ($^O =~ 'msys' || $^O =~ 'cygwin') {
 | 
				
			||||||
 | 
						$git_work_tree = Win32::GetCwd();
 | 
				
			||||||
 | 
						$git_work_tree =~ tr/\\/\//;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						require Cwd;
 | 
				
			||||||
 | 
						$git_work_tree = Cwd::cwd();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $retry = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					launch_watchman();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub launch_watchman {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
 | 
				
			||||||
 | 
						    or die "open2() failed: $!\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# In the query expression below we're asking for names of files that
 | 
				
			||||||
 | 
						# changed since $time but were not transient (ie created after
 | 
				
			||||||
 | 
						# $time but no longer exist).
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# To accomplish this, we're using the "since" generator to use the
 | 
				
			||||||
 | 
						# recency index to select candidate nodes and "fields" to limit the
 | 
				
			||||||
 | 
						# output to file names only. Then we're using the "expression" term to
 | 
				
			||||||
 | 
						# further constrain the results.
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# The category of transient files that we want to ignore will have a
 | 
				
			||||||
 | 
						# creation clock (cclock) newer than $time_t value and will also not
 | 
				
			||||||
 | 
						# currently exist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $query = <<"	END";
 | 
				
			||||||
 | 
							["query", "$git_work_tree", {
 | 
				
			||||||
 | 
								"since": $time,
 | 
				
			||||||
 | 
								"fields": ["name"],
 | 
				
			||||||
 | 
								"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
 | 
				
			||||||
 | 
							}]
 | 
				
			||||||
 | 
						END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print CHLD_IN $query;
 | 
				
			||||||
 | 
						close CHLD_IN;
 | 
				
			||||||
 | 
						my $response = do {local $/; <CHLD_OUT>};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: command returned no output.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $response eq "";
 | 
				
			||||||
 | 
						die "Watchman: command returned invalid output: $response\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" unless $response =~ /^\{/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $json_pkg;
 | 
				
			||||||
 | 
						eval {
 | 
				
			||||||
 | 
							require JSON::XS;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::XS";
 | 
				
			||||||
 | 
							1;
 | 
				
			||||||
 | 
						} or do {
 | 
				
			||||||
 | 
							require JSON::PP;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::PP";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $o = $json_pkg->new->utf8->decode($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
 | 
				
			||||||
 | 
							print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
 | 
				
			||||||
 | 
							$retry--;
 | 
				
			||||||
 | 
							qx/watchman watch "$git_work_tree"/;
 | 
				
			||||||
 | 
							die "Failed to make watchman watch '$git_work_tree'.\n" .
 | 
				
			||||||
 | 
							    "Falling back to scanning...\n" if $? != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Watchman will always return all files on the first query so
 | 
				
			||||||
 | 
							# return the fast "everything is dirty" flag to git and do the
 | 
				
			||||||
 | 
							# Watchman query just to get it over with now so we won't pay
 | 
				
			||||||
 | 
							# the cost in git to look up each individual file.
 | 
				
			||||||
 | 
							print "/\0";
 | 
				
			||||||
 | 
							eval { launch_watchman() };
 | 
				
			||||||
 | 
							exit 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: $o->{error}.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $o->{error};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binmode STDOUT, ":utf8";
 | 
				
			||||||
 | 
						local $, = "\0";
 | 
				
			||||||
 | 
						print @{$o->{files}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare a packed repository for use over
 | 
				
			||||||
 | 
					# dumb transports.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "post-update".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec git update-server-info
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed
 | 
				
			||||||
 | 
					# by applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-applypatch".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					precommit="$(git rev-parse --git-path hooks/pre-commit)"
 | 
				
			||||||
 | 
					test -x "$precommit" && exec "$precommit" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed.
 | 
				
			||||||
 | 
					# Called by "git commit" with no arguments.  The hook should
 | 
				
			||||||
 | 
					# exit with non-zero status after issuing an appropriate message if
 | 
				
			||||||
 | 
					# it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-commit".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if git rev-parse --verify HEAD >/dev/null 2>&1
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						against=HEAD
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						# Initial commit: diff against an empty tree object
 | 
				
			||||||
 | 
						against=$(git hash-object -t tree /dev/null)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you want to allow non-ASCII filenames set this variable to true.
 | 
				
			||||||
 | 
					allownonascii=$(git config --bool hooks.allownonascii)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Redirect output to stderr.
 | 
				
			||||||
 | 
					exec 1>&2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cross platform projects tend to avoid non-ASCII filenames; prevent
 | 
				
			||||||
 | 
					# them from being added to the repository. We exploit the fact that the
 | 
				
			||||||
 | 
					# printable range starts at the space character and ends with tilde.
 | 
				
			||||||
 | 
					if [ "$allownonascii" != "true" ] &&
 | 
				
			||||||
 | 
						# Note that the use of brackets around a tr range is ok here, (it's
 | 
				
			||||||
 | 
						# even required, for portability to Solaris 10's /usr/bin/tr), since
 | 
				
			||||||
 | 
						# the square bracket bytes happen to fall in the designated range.
 | 
				
			||||||
 | 
						test $(git diff --cached --name-only --diff-filter=A -z $against |
 | 
				
			||||||
 | 
						  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						cat <<\EOF
 | 
				
			||||||
 | 
					Error: Attempt to add a non-ASCII file name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can cause problems if you want to work with people on other platforms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To be portable it is advisable to rename the file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know what you are doing you can disable this check using:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  git config hooks.allownonascii true
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If there are whitespace errors, print the offending file names and fail.
 | 
				
			||||||
 | 
					exec git diff-index --check --cached $against --
 | 
				
			||||||
@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be pushed.  Called by "git
 | 
				
			||||||
 | 
					# push" after it has checked the remote status, but before anything has been
 | 
				
			||||||
 | 
					# pushed.  If this script exits with a non-zero status nothing will be pushed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- Name of the remote to which the push is being done
 | 
				
			||||||
 | 
					# $2 -- URL to which the push is being done
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If pushing without using a named remote those arguments will be equal.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Information about the commits which are being pushed is supplied as lines to
 | 
				
			||||||
 | 
					# the standard input in the form:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   <local ref> <local sha1> <remote ref> <remote sha1>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent push of commits where the log message starts
 | 
				
			||||||
 | 
					# with "WIP" (work in progress).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remote="$1"
 | 
				
			||||||
 | 
					url="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					z40=0000000000000000000000000000000000000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while read local_ref local_sha remote_ref remote_sha
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						if [ "$local_sha" = $z40 ]
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							# Handle delete
 | 
				
			||||||
 | 
							:
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							if [ "$remote_sha" = $z40 ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								# New branch, examine all commits
 | 
				
			||||||
 | 
								range="$local_sha"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								# Update to existing branch, examine new commits
 | 
				
			||||||
 | 
								range="$remote_sha..$local_sha"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Check for WIP commit
 | 
				
			||||||
 | 
							commit=`git rev-list -n 1 --grep '^WIP' "$range"`
 | 
				
			||||||
 | 
							if [ -n "$commit" ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo >&2 "Found WIP commit in $local_ref, not pushing"
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2006, 2008 Junio C Hamano
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The "pre-rebase" hook is run just before "git rebase" starts doing
 | 
				
			||||||
 | 
					# its job, and can prevent the command from running by exiting with
 | 
				
			||||||
 | 
					# non-zero status.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- the upstream the series was forked from.
 | 
				
			||||||
 | 
					# $2 -- the branch being rebased (or empty when rebasing the current branch).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent topic branches that are already
 | 
				
			||||||
 | 
					# merged to 'next' branch from getting rebased, because allowing it
 | 
				
			||||||
 | 
					# would result in rebasing already published history.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish=next
 | 
				
			||||||
 | 
					basebranch="$1"
 | 
				
			||||||
 | 
					if test "$#" = 2
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						topic="refs/heads/$2"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						topic=`git symbolic-ref HEAD` ||
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt rebasing detached HEAD
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$topic" in
 | 
				
			||||||
 | 
					refs/heads/??/*)
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					*)
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt others.
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Now we are dealing with a topic branch being rebased
 | 
				
			||||||
 | 
					# on top of master.  Is it OK to rebase it?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Does the topic really exist?
 | 
				
			||||||
 | 
					git show-ref -q "$topic" || {
 | 
				
			||||||
 | 
						echo >&2 "No such branch $topic"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic fully merged to master?
 | 
				
			||||||
 | 
					not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
 | 
				
			||||||
 | 
					if test -z "$not_in_master"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						echo >&2 "$topic is fully merged to master; better remove it."
 | 
				
			||||||
 | 
						exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic ever merged to next?  If so you should not be rebasing it.
 | 
				
			||||||
 | 
					only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
 | 
				
			||||||
 | 
					only_next_2=`git rev-list ^master           ${publish} | sort`
 | 
				
			||||||
 | 
					if test "$only_next_1" = "$only_next_2"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						not_in_topic=`git rev-list "^$topic" master`
 | 
				
			||||||
 | 
						if test -z "$not_in_topic"
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							echo >&2 "$topic is already up to date with master"
 | 
				
			||||||
 | 
							exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
 | 
				
			||||||
 | 
						/usr/bin/perl -e '
 | 
				
			||||||
 | 
							my $topic = $ARGV[0];
 | 
				
			||||||
 | 
							my $msg = "* $topic has commits already merged to public branch:\n";
 | 
				
			||||||
 | 
							my (%not_in_next) = map {
 | 
				
			||||||
 | 
								/^([0-9a-f]+) /;
 | 
				
			||||||
 | 
								($1 => 1);
 | 
				
			||||||
 | 
							} split(/\n/, $ARGV[1]);
 | 
				
			||||||
 | 
							for my $elem (map {
 | 
				
			||||||
 | 
									/^([0-9a-f]+) (.*)$/;
 | 
				
			||||||
 | 
									[$1 => $2];
 | 
				
			||||||
 | 
								} split(/\n/, $ARGV[2])) {
 | 
				
			||||||
 | 
								if (!exists $not_in_next{$elem->[0]}) {
 | 
				
			||||||
 | 
									if ($msg) {
 | 
				
			||||||
 | 
										print STDERR $msg;
 | 
				
			||||||
 | 
										undef $msg;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									print STDERR " $elem->[1]\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						' "$topic" "$not_in_next" "$not_in_master"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<\DOC_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This sample hook safeguards topic branches that have been
 | 
				
			||||||
 | 
					published from being rewound.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The workflow assumed here is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch forks from "master", "master" is never
 | 
				
			||||||
 | 
					   merged into it again (either directly or indirectly).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch is fully cooked and merged into "master",
 | 
				
			||||||
 | 
					   it is deleted.  If you need to build on top of it to correct
 | 
				
			||||||
 | 
					   earlier mistakes, a new topic branch is created by forking at
 | 
				
			||||||
 | 
					   the tip of the "master".  This is not strictly necessary, but
 | 
				
			||||||
 | 
					   it makes it easier to keep your history simple.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Whenever you need to test or publish your changes to topic
 | 
				
			||||||
 | 
					   branches, merge them into "next" branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The script, being an example, hardcodes the publish branch name
 | 
				
			||||||
 | 
					to be "next", but it is trivial to make it configurable via
 | 
				
			||||||
 | 
					$GIT_DIR/config mechanism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With this workflow, you would want to know:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(1) ... if a topic branch has ever been merged to "next".  Young
 | 
				
			||||||
 | 
					    topic branches can have stupid mistakes you would rather
 | 
				
			||||||
 | 
					    clean up before publishing, and things that have not been
 | 
				
			||||||
 | 
					    merged into other branches can be easily rebased without
 | 
				
			||||||
 | 
					    affecting other people.  But once it is published, you would
 | 
				
			||||||
 | 
					    not want to rewind it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(2) ... if a topic branch has been fully merged to "master".
 | 
				
			||||||
 | 
					    Then you can delete it.  More importantly, you should not
 | 
				
			||||||
 | 
					    build on top of it -- other people may already want to
 | 
				
			||||||
 | 
					    change things related to the topic as patches against your
 | 
				
			||||||
 | 
					    "master", so if you need further changes, it is better to
 | 
				
			||||||
 | 
					    fork the topic (perhaps with the same name) afresh from the
 | 
				
			||||||
 | 
					    tip of "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's look at this example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							   o---o---o---o---o---o---o---o---o---o "next"
 | 
				
			||||||
 | 
							  /       /           /           /
 | 
				
			||||||
 | 
							 /   a---a---b A     /           /
 | 
				
			||||||
 | 
							/   /               /           /
 | 
				
			||||||
 | 
						       /   /   c---c---c---c B         /
 | 
				
			||||||
 | 
						      /   /   /             \         /
 | 
				
			||||||
 | 
						     /   /   /   b---b C     \       /
 | 
				
			||||||
 | 
						    /   /   /   /             \     /
 | 
				
			||||||
 | 
					    ---o---o---o---o---o---o---o---o---o---o---o "master"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A, B and C are topic branches.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * A has one fix since it was merged up to "next".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * B has finished.  It has been fully merged up to "master" and "next",
 | 
				
			||||||
 | 
					   and is ready to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * C has not merged to "next" at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We would want to allow C to be rebased, refuse A, and encourage
 | 
				
			||||||
 | 
					B to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list ^master ^topic next
 | 
				
			||||||
 | 
						git rev-list ^master        next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if these match, topic has not merged in next at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (2):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list master..topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if this is empty, it is fully merged to "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DOC_END
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to make use of push options.
 | 
				
			||||||
 | 
					# The example simply echoes all push options that start with 'echoback='
 | 
				
			||||||
 | 
					# and rejects all pushes when the "reject" push option is used.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-receive".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						i=0
 | 
				
			||||||
 | 
						while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
						do
 | 
				
			||||||
 | 
							eval "value=\$GIT_PUSH_OPTION_$i"
 | 
				
			||||||
 | 
							case "$value" in
 | 
				
			||||||
 | 
							echoback=*)
 | 
				
			||||||
 | 
								echo "echo from the pre-receive-hook: ${value#*=}" >&2
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							reject)
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							i=$((i + 1))
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with the name of the file that has the
 | 
				
			||||||
 | 
					# commit message, followed by the description of the commit
 | 
				
			||||||
 | 
					# message's source.  The hook's purpose is to edit the commit
 | 
				
			||||||
 | 
					# message file.  If the hook fails with a non-zero status,
 | 
				
			||||||
 | 
					# the commit is aborted.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "prepare-commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This hook includes three examples. The first one removes the
 | 
				
			||||||
 | 
					# "# Please enter the commit message..." help message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The second includes the output of "git diff --name-status -r"
 | 
				
			||||||
 | 
					# into the message, just before the "git status" output.  It is
 | 
				
			||||||
 | 
					# commented because it doesn't cope with --amend or with squashed
 | 
				
			||||||
 | 
					# commits.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The third example adds a Signed-off-by line to the message, that can
 | 
				
			||||||
 | 
					# still be edited.  This is rarely a good idea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT_MSG_FILE=$1
 | 
				
			||||||
 | 
					COMMIT_SOURCE=$2
 | 
				
			||||||
 | 
					SHA1=$3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# case "$COMMIT_SOURCE,$SHA1" in
 | 
				
			||||||
 | 
					#  ,|template,)
 | 
				
			||||||
 | 
					#    /usr/bin/perl -i.bak -pe '
 | 
				
			||||||
 | 
					#       print "\n" . `git diff --cached --name-status -r`
 | 
				
			||||||
 | 
					# 	 if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
 | 
				
			||||||
 | 
					#  *) ;;
 | 
				
			||||||
 | 
					# esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# if test -z "$COMMIT_SOURCE"
 | 
				
			||||||
 | 
					# then
 | 
				
			||||||
 | 
					#   /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# fi
 | 
				
			||||||
@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to block unannotated tags from entering.
 | 
				
			||||||
 | 
					# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "update".
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Config
 | 
				
			||||||
 | 
					# ------
 | 
				
			||||||
 | 
					# hooks.allowunannotated
 | 
				
			||||||
 | 
					#   This boolean sets whether unannotated tags will be allowed into the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletetag
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting tags will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowmodifytag
 | 
				
			||||||
 | 
					#   This boolean sets whether a tag may be modified after creation. By default
 | 
				
			||||||
 | 
					#   it won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting branches will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.denycreatebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether remotely creating branches will be denied
 | 
				
			||||||
 | 
					#   in the repository.  By default this is allowed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Command line
 | 
				
			||||||
 | 
					refname="$1"
 | 
				
			||||||
 | 
					oldrev="$2"
 | 
				
			||||||
 | 
					newrev="$3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Safety check
 | 
				
			||||||
 | 
					if [ -z "$GIT_DIR" ]; then
 | 
				
			||||||
 | 
						echo "Don't run this script from the command line." >&2
 | 
				
			||||||
 | 
						echo " (if you want, you could supply GIT_DIR then run" >&2
 | 
				
			||||||
 | 
						echo "  $0 <ref> <oldrev> <newrev>)" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
 | 
				
			||||||
 | 
						echo "usage: $0 <ref> <oldrev> <newrev>" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Config
 | 
				
			||||||
 | 
					allowunannotated=$(git config --bool hooks.allowunannotated)
 | 
				
			||||||
 | 
					allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
 | 
				
			||||||
 | 
					denycreatebranch=$(git config --bool hooks.denycreatebranch)
 | 
				
			||||||
 | 
					allowdeletetag=$(git config --bool hooks.allowdeletetag)
 | 
				
			||||||
 | 
					allowmodifytag=$(git config --bool hooks.allowmodifytag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for no description
 | 
				
			||||||
 | 
					projectdesc=$(sed -e '1q' "$GIT_DIR/description")
 | 
				
			||||||
 | 
					case "$projectdesc" in
 | 
				
			||||||
 | 
					"Unnamed repository"* | "")
 | 
				
			||||||
 | 
						echo "*** Project description file hasn't been set" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Check types
 | 
				
			||||||
 | 
					# if $newrev is 0000...0000, it's a commit to delete a ref.
 | 
				
			||||||
 | 
					zero="0000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					if [ "$newrev" = "$zero" ]; then
 | 
				
			||||||
 | 
						newrev_type=delete
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						newrev_type=$(git cat-file -t $newrev)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$refname","$newrev_type" in
 | 
				
			||||||
 | 
						refs/tags/*,commit)
 | 
				
			||||||
 | 
							# un-annotated tag
 | 
				
			||||||
 | 
							short_refname=${refname##refs/tags/}
 | 
				
			||||||
 | 
							if [ "$allowunannotated" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,delete)
 | 
				
			||||||
 | 
							# delete tag
 | 
				
			||||||
 | 
							if [ "$allowdeletetag" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tag is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,tag)
 | 
				
			||||||
 | 
							# annotated tag
 | 
				
			||||||
 | 
							if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo "*** Tag '$refname' already exists." >&2
 | 
				
			||||||
 | 
								echo "*** Modifying a tag is not allowed in this repository." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,commit)
 | 
				
			||||||
 | 
							# branch
 | 
				
			||||||
 | 
							if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Creating a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,delete)
 | 
				
			||||||
 | 
							# delete branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,commit)
 | 
				
			||||||
 | 
							# tracking branch
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,delete)
 | 
				
			||||||
 | 
							# delete tracking branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tracking branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						*)
 | 
				
			||||||
 | 
							# Anything else (is there anything else?)
 | 
				
			||||||
 | 
							echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Finished
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# git ls-files --others --exclude-from=.git/info/exclude
 | 
				
			||||||
 | 
					# Lines that start with '#' are comments.
 | 
				
			||||||
 | 
					# For a project mostly in C, the following would be a good set of
 | 
				
			||||||
 | 
					# exclude patterns (uncomment them if you want to use them):
 | 
				
			||||||
 | 
					# *.[oa]
 | 
				
			||||||
 | 
					# *~
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					6e75c9f89da9a9b93f4f36e61ed092f7a1625ba0
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ref: refs/heads/master
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					[core]
 | 
				
			||||||
 | 
						repositoryformatversion = 0
 | 
				
			||||||
 | 
						filemode = true
 | 
				
			||||||
 | 
						bare = true
 | 
				
			||||||
 | 
						ignorecase = true
 | 
				
			||||||
 | 
						precomposeunicode = true
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Unnamed repository; edit this file 'description' to name the repository.
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message taken by
 | 
				
			||||||
 | 
					# applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.  The hook is
 | 
				
			||||||
 | 
					# allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "applypatch-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
 | 
				
			||||||
 | 
					test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with one argument, the name of the file
 | 
				
			||||||
 | 
					# that has the commit message.  The hook should exit with non-zero
 | 
				
			||||||
 | 
					# status after issuing an appropriate message if it wants to stop the
 | 
				
			||||||
 | 
					# commit.  The hook is allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment the below to add a Signed-off-by line to the message.
 | 
				
			||||||
 | 
					# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
 | 
				
			||||||
 | 
					# hook is more suited to it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This example catches duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "" = "$(grep '^Signed-off-by: ' "$1" |
 | 
				
			||||||
 | 
						 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
 | 
				
			||||||
 | 
						echo >&2 Duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,114 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/perl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					use strict;
 | 
				
			||||||
 | 
					use warnings;
 | 
				
			||||||
 | 
					use IPC::Open2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to integrate Watchman
 | 
				
			||||||
 | 
					# (https://facebook.github.io/watchman/) with git to speed up detecting
 | 
				
			||||||
 | 
					# new and modified files.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is passed a version (currently 1) and a time in nanoseconds
 | 
				
			||||||
 | 
					# formatted as a string and outputs to stdout all files that have been
 | 
				
			||||||
 | 
					# modified since the given time. Paths must be relative to the root of
 | 
				
			||||||
 | 
					# the working tree and separated by a single NUL.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "query-watchman" and set
 | 
				
			||||||
 | 
					# 'git config core.fsmonitor .git/hooks/query-watchman'
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					my ($version, $time) = @ARGV;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Check the hook interface version
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if ($version == 1) {
 | 
				
			||||||
 | 
						# convert nanoseconds to seconds
 | 
				
			||||||
 | 
						$time = int $time / 1000000000;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						die "Unsupported query-fsmonitor hook version '$version'.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $git_work_tree;
 | 
				
			||||||
 | 
					if ($^O =~ 'msys' || $^O =~ 'cygwin') {
 | 
				
			||||||
 | 
						$git_work_tree = Win32::GetCwd();
 | 
				
			||||||
 | 
						$git_work_tree =~ tr/\\/\//;
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
						require Cwd;
 | 
				
			||||||
 | 
						$git_work_tree = Cwd::cwd();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					my $retry = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					launch_watchman();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					sub launch_watchman {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $pid = open2(\*CHLD_OUT, \*CHLD_IN, 'watchman -j --no-pretty')
 | 
				
			||||||
 | 
						    or die "open2() failed: $!\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# In the query expression below we're asking for names of files that
 | 
				
			||||||
 | 
						# changed since $time but were not transient (ie created after
 | 
				
			||||||
 | 
						# $time but no longer exist).
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# To accomplish this, we're using the "since" generator to use the
 | 
				
			||||||
 | 
						# recency index to select candidate nodes and "fields" to limit the
 | 
				
			||||||
 | 
						# output to file names only. Then we're using the "expression" term to
 | 
				
			||||||
 | 
						# further constrain the results.
 | 
				
			||||||
 | 
						#
 | 
				
			||||||
 | 
						# The category of transient files that we want to ignore will have a
 | 
				
			||||||
 | 
						# creation clock (cclock) newer than $time_t value and will also not
 | 
				
			||||||
 | 
						# currently exist.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $query = <<"	END";
 | 
				
			||||||
 | 
							["query", "$git_work_tree", {
 | 
				
			||||||
 | 
								"since": $time,
 | 
				
			||||||
 | 
								"fields": ["name"],
 | 
				
			||||||
 | 
								"expression": ["not", ["allof", ["since", $time, "cclock"], ["not", "exists"]]]
 | 
				
			||||||
 | 
							}]
 | 
				
			||||||
 | 
						END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						print CHLD_IN $query;
 | 
				
			||||||
 | 
						close CHLD_IN;
 | 
				
			||||||
 | 
						my $response = do {local $/; <CHLD_OUT>};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: command returned no output.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $response eq "";
 | 
				
			||||||
 | 
						die "Watchman: command returned invalid output: $response\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" unless $response =~ /^\{/;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $json_pkg;
 | 
				
			||||||
 | 
						eval {
 | 
				
			||||||
 | 
							require JSON::XS;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::XS";
 | 
				
			||||||
 | 
							1;
 | 
				
			||||||
 | 
						} or do {
 | 
				
			||||||
 | 
							require JSON::PP;
 | 
				
			||||||
 | 
							$json_pkg = "JSON::PP";
 | 
				
			||||||
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						my $o = $json_pkg->new->utf8->decode($response);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if ($retry > 0 and $o->{error} and $o->{error} =~ m/unable to resolve root .* directory (.*) is not watched/) {
 | 
				
			||||||
 | 
							print STDERR "Adding '$git_work_tree' to watchman's watch list.\n";
 | 
				
			||||||
 | 
							$retry--;
 | 
				
			||||||
 | 
							qx/watchman watch "$git_work_tree"/;
 | 
				
			||||||
 | 
							die "Failed to make watchman watch '$git_work_tree'.\n" .
 | 
				
			||||||
 | 
							    "Falling back to scanning...\n" if $? != 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Watchman will always return all files on the first query so
 | 
				
			||||||
 | 
							# return the fast "everything is dirty" flag to git and do the
 | 
				
			||||||
 | 
							# Watchman query just to get it over with now so we won't pay
 | 
				
			||||||
 | 
							# the cost in git to look up each individual file.
 | 
				
			||||||
 | 
							print "/\0";
 | 
				
			||||||
 | 
							eval { launch_watchman() };
 | 
				
			||||||
 | 
							exit 0;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						die "Watchman: $o->{error}.\n" .
 | 
				
			||||||
 | 
						    "Falling back to scanning...\n" if $o->{error};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						binmode STDOUT, ":utf8";
 | 
				
			||||||
 | 
						local $, = "\0";
 | 
				
			||||||
 | 
						print @{$o->{files}};
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare a packed repository for use over
 | 
				
			||||||
 | 
					# dumb transports.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "post-update".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exec git update-server-info
 | 
				
			||||||
@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed
 | 
				
			||||||
 | 
					# by applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-applypatch".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					precommit="$(git rev-parse --git-path hooks/pre-commit)"
 | 
				
			||||||
 | 
					test -x "$precommit" && exec "$precommit" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be committed.
 | 
				
			||||||
 | 
					# Called by "git commit" with no arguments.  The hook should
 | 
				
			||||||
 | 
					# exit with non-zero status after issuing an appropriate message if
 | 
				
			||||||
 | 
					# it wants to stop the commit.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-commit".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if git rev-parse --verify HEAD >/dev/null 2>&1
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						against=HEAD
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						# Initial commit: diff against an empty tree object
 | 
				
			||||||
 | 
						against=$(git hash-object -t tree /dev/null)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you want to allow non-ASCII filenames set this variable to true.
 | 
				
			||||||
 | 
					allownonascii=$(git config --bool hooks.allownonascii)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Redirect output to stderr.
 | 
				
			||||||
 | 
					exec 1>&2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Cross platform projects tend to avoid non-ASCII filenames; prevent
 | 
				
			||||||
 | 
					# them from being added to the repository. We exploit the fact that the
 | 
				
			||||||
 | 
					# printable range starts at the space character and ends with tilde.
 | 
				
			||||||
 | 
					if [ "$allownonascii" != "true" ] &&
 | 
				
			||||||
 | 
						# Note that the use of brackets around a tr range is ok here, (it's
 | 
				
			||||||
 | 
						# even required, for portability to Solaris 10's /usr/bin/tr), since
 | 
				
			||||||
 | 
						# the square bracket bytes happen to fall in the designated range.
 | 
				
			||||||
 | 
						test $(git diff --cached --name-only --diff-filter=A -z $against |
 | 
				
			||||||
 | 
						  LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						cat <<\EOF
 | 
				
			||||||
 | 
					Error: Attempt to add a non-ASCII file name.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This can cause problems if you want to work with people on other platforms.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To be portable it is advisable to rename the file.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					If you know what you are doing you can disable this check using:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  git config hooks.allownonascii true
 | 
				
			||||||
 | 
					EOF
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If there are whitespace errors, print the offending file names and fail.
 | 
				
			||||||
 | 
					exec git diff-index --check --cached $against --
 | 
				
			||||||
@@ -0,0 +1,53 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# An example hook script to verify what is about to be pushed.  Called by "git
 | 
				
			||||||
 | 
					# push" after it has checked the remote status, but before anything has been
 | 
				
			||||||
 | 
					# pushed.  If this script exits with a non-zero status nothing will be pushed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- Name of the remote to which the push is being done
 | 
				
			||||||
 | 
					# $2 -- URL to which the push is being done
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# If pushing without using a named remote those arguments will be equal.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Information about the commits which are being pushed is supplied as lines to
 | 
				
			||||||
 | 
					# the standard input in the form:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					#   <local ref> <local sha1> <remote ref> <remote sha1>
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent push of commits where the log message starts
 | 
				
			||||||
 | 
					# with "WIP" (work in progress).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remote="$1"
 | 
				
			||||||
 | 
					url="$2"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					z40=0000000000000000000000000000000000000000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					while read local_ref local_sha remote_ref remote_sha
 | 
				
			||||||
 | 
					do
 | 
				
			||||||
 | 
						if [ "$local_sha" = $z40 ]
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							# Handle delete
 | 
				
			||||||
 | 
							:
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							if [ "$remote_sha" = $z40 ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								# New branch, examine all commits
 | 
				
			||||||
 | 
								range="$local_sha"
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								# Update to existing branch, examine new commits
 | 
				
			||||||
 | 
								range="$remote_sha..$local_sha"
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							# Check for WIP commit
 | 
				
			||||||
 | 
							commit=`git rev-list -n 1 --grep '^WIP' "$range"`
 | 
				
			||||||
 | 
							if [ -n "$commit" ]
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo >&2 "Found WIP commit in $local_ref, not pushing"
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,169 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Copyright (c) 2006, 2008 Junio C Hamano
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The "pre-rebase" hook is run just before "git rebase" starts doing
 | 
				
			||||||
 | 
					# its job, and can prevent the command from running by exiting with
 | 
				
			||||||
 | 
					# non-zero status.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook is called with the following parameters:
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# $1 -- the upstream the series was forked from.
 | 
				
			||||||
 | 
					# $2 -- the branch being rebased (or empty when rebasing the current branch).
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# This sample shows how to prevent topic branches that are already
 | 
				
			||||||
 | 
					# merged to 'next' branch from getting rebased, because allowing it
 | 
				
			||||||
 | 
					# would result in rebasing already published history.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					publish=next
 | 
				
			||||||
 | 
					basebranch="$1"
 | 
				
			||||||
 | 
					if test "$#" = 2
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						topic="refs/heads/$2"
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						topic=`git symbolic-ref HEAD` ||
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt rebasing detached HEAD
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$topic" in
 | 
				
			||||||
 | 
					refs/heads/??/*)
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					*)
 | 
				
			||||||
 | 
						exit 0 ;# we do not interrupt others.
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Now we are dealing with a topic branch being rebased
 | 
				
			||||||
 | 
					# on top of master.  Is it OK to rebase it?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Does the topic really exist?
 | 
				
			||||||
 | 
					git show-ref -q "$topic" || {
 | 
				
			||||||
 | 
						echo >&2 "No such branch $topic"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic fully merged to master?
 | 
				
			||||||
 | 
					not_in_master=`git rev-list --pretty=oneline ^master "$topic"`
 | 
				
			||||||
 | 
					if test -z "$not_in_master"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						echo >&2 "$topic is fully merged to master; better remove it."
 | 
				
			||||||
 | 
						exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Is topic ever merged to next?  If so you should not be rebasing it.
 | 
				
			||||||
 | 
					only_next_1=`git rev-list ^master "^$topic" ${publish} | sort`
 | 
				
			||||||
 | 
					only_next_2=`git rev-list ^master           ${publish} | sort`
 | 
				
			||||||
 | 
					if test "$only_next_1" = "$only_next_2"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						not_in_topic=`git rev-list "^$topic" master`
 | 
				
			||||||
 | 
						if test -z "$not_in_topic"
 | 
				
			||||||
 | 
						then
 | 
				
			||||||
 | 
							echo >&2 "$topic is already up to date with master"
 | 
				
			||||||
 | 
							exit 1 ;# we could allow it, but there is no point.
 | 
				
			||||||
 | 
						else
 | 
				
			||||||
 | 
							exit 0
 | 
				
			||||||
 | 
						fi
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						not_in_next=`git rev-list --pretty=oneline ^${publish} "$topic"`
 | 
				
			||||||
 | 
						/usr/bin/perl -e '
 | 
				
			||||||
 | 
							my $topic = $ARGV[0];
 | 
				
			||||||
 | 
							my $msg = "* $topic has commits already merged to public branch:\n";
 | 
				
			||||||
 | 
							my (%not_in_next) = map {
 | 
				
			||||||
 | 
								/^([0-9a-f]+) /;
 | 
				
			||||||
 | 
								($1 => 1);
 | 
				
			||||||
 | 
							} split(/\n/, $ARGV[1]);
 | 
				
			||||||
 | 
							for my $elem (map {
 | 
				
			||||||
 | 
									/^([0-9a-f]+) (.*)$/;
 | 
				
			||||||
 | 
									[$1 => $2];
 | 
				
			||||||
 | 
								} split(/\n/, $ARGV[2])) {
 | 
				
			||||||
 | 
								if (!exists $not_in_next{$elem->[0]}) {
 | 
				
			||||||
 | 
									if ($msg) {
 | 
				
			||||||
 | 
										print STDERR $msg;
 | 
				
			||||||
 | 
										undef $msg;
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
									print STDERR " $elem->[1]\n";
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						' "$topic" "$not_in_next" "$not_in_master"
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<<\DOC_END
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					This sample hook safeguards topic branches that have been
 | 
				
			||||||
 | 
					published from being rewound.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The workflow assumed here is:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch forks from "master", "master" is never
 | 
				
			||||||
 | 
					   merged into it again (either directly or indirectly).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Once a topic branch is fully cooked and merged into "master",
 | 
				
			||||||
 | 
					   it is deleted.  If you need to build on top of it to correct
 | 
				
			||||||
 | 
					   earlier mistakes, a new topic branch is created by forking at
 | 
				
			||||||
 | 
					   the tip of the "master".  This is not strictly necessary, but
 | 
				
			||||||
 | 
					   it makes it easier to keep your history simple.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * Whenever you need to test or publish your changes to topic
 | 
				
			||||||
 | 
					   branches, merge them into "next" branch.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					The script, being an example, hardcodes the publish branch name
 | 
				
			||||||
 | 
					to be "next", but it is trivial to make it configurable via
 | 
				
			||||||
 | 
					$GIT_DIR/config mechanism.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					With this workflow, you would want to know:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(1) ... if a topic branch has ever been merged to "next".  Young
 | 
				
			||||||
 | 
					    topic branches can have stupid mistakes you would rather
 | 
				
			||||||
 | 
					    clean up before publishing, and things that have not been
 | 
				
			||||||
 | 
					    merged into other branches can be easily rebased without
 | 
				
			||||||
 | 
					    affecting other people.  But once it is published, you would
 | 
				
			||||||
 | 
					    not want to rewind it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					(2) ... if a topic branch has been fully merged to "master".
 | 
				
			||||||
 | 
					    Then you can delete it.  More importantly, you should not
 | 
				
			||||||
 | 
					    build on top of it -- other people may already want to
 | 
				
			||||||
 | 
					    change things related to the topic as patches against your
 | 
				
			||||||
 | 
					    "master", so if you need further changes, it is better to
 | 
				
			||||||
 | 
					    fork the topic (perhaps with the same name) afresh from the
 | 
				
			||||||
 | 
					    tip of "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Let's look at this example:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							   o---o---o---o---o---o---o---o---o---o "next"
 | 
				
			||||||
 | 
							  /       /           /           /
 | 
				
			||||||
 | 
							 /   a---a---b A     /           /
 | 
				
			||||||
 | 
							/   /               /           /
 | 
				
			||||||
 | 
						       /   /   c---c---c---c B         /
 | 
				
			||||||
 | 
						      /   /   /             \         /
 | 
				
			||||||
 | 
						     /   /   /   b---b C     \       /
 | 
				
			||||||
 | 
						    /   /   /   /             \     /
 | 
				
			||||||
 | 
					    ---o---o---o---o---o---o---o---o---o---o---o "master"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					A, B and C are topic branches.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * A has one fix since it was merged up to "next".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * B has finished.  It has been fully merged up to "master" and "next",
 | 
				
			||||||
 | 
					   and is ready to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 * C has not merged to "next" at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					We would want to allow C to be rebased, refuse A, and encourage
 | 
				
			||||||
 | 
					B to be deleted.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (1):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list ^master ^topic next
 | 
				
			||||||
 | 
						git rev-list ^master        next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if these match, topic has not merged in next at all.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To compute (2):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						git rev-list master..topic
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if this is empty, it is fully merged to "master".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					DOC_END
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to make use of push options.
 | 
				
			||||||
 | 
					# The example simply echoes all push options that start with 'echoback='
 | 
				
			||||||
 | 
					# and rejects all pushes when the "reject" push option is used.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "pre-receive".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if test -n "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
					then
 | 
				
			||||||
 | 
						i=0
 | 
				
			||||||
 | 
						while test "$i" -lt "$GIT_PUSH_OPTION_COUNT"
 | 
				
			||||||
 | 
						do
 | 
				
			||||||
 | 
							eval "value=\$GIT_PUSH_OPTION_$i"
 | 
				
			||||||
 | 
							case "$value" in
 | 
				
			||||||
 | 
							echoback=*)
 | 
				
			||||||
 | 
								echo "echo from the pre-receive-hook: ${value#*=}" >&2
 | 
				
			||||||
 | 
								;;
 | 
				
			||||||
 | 
							reject)
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							esac
 | 
				
			||||||
 | 
							i=$((i + 1))
 | 
				
			||||||
 | 
						done
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
@@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to prepare the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with the name of the file that has the
 | 
				
			||||||
 | 
					# commit message, followed by the description of the commit
 | 
				
			||||||
 | 
					# message's source.  The hook's purpose is to edit the commit
 | 
				
			||||||
 | 
					# message file.  If the hook fails with a non-zero status,
 | 
				
			||||||
 | 
					# the commit is aborted.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "prepare-commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This hook includes three examples. The first one removes the
 | 
				
			||||||
 | 
					# "# Please enter the commit message..." help message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The second includes the output of "git diff --name-status -r"
 | 
				
			||||||
 | 
					# into the message, just before the "git status" output.  It is
 | 
				
			||||||
 | 
					# commented because it doesn't cope with --amend or with squashed
 | 
				
			||||||
 | 
					# commits.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The third example adds a Signed-off-by line to the message, that can
 | 
				
			||||||
 | 
					# still be edited.  This is rarely a good idea.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					COMMIT_MSG_FILE=$1
 | 
				
			||||||
 | 
					COMMIT_SOURCE=$2
 | 
				
			||||||
 | 
					SHA1=$3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/usr/bin/perl -i.bak -ne 'print unless(m/^. Please enter the commit message/..m/^#$/)' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# case "$COMMIT_SOURCE,$SHA1" in
 | 
				
			||||||
 | 
					#  ,|template,)
 | 
				
			||||||
 | 
					#    /usr/bin/perl -i.bak -pe '
 | 
				
			||||||
 | 
					#       print "\n" . `git diff --cached --name-status -r`
 | 
				
			||||||
 | 
					# 	 if /^#/ && $first++ == 0' "$COMMIT_MSG_FILE" ;;
 | 
				
			||||||
 | 
					#  *) ;;
 | 
				
			||||||
 | 
					# esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_COMMITTER_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# git interpret-trailers --in-place --trailer "$SOB" "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# if test -z "$COMMIT_SOURCE"
 | 
				
			||||||
 | 
					# then
 | 
				
			||||||
 | 
					#   /usr/bin/perl -i.bak -pe 'print "\n" if !$first_line++' "$COMMIT_MSG_FILE"
 | 
				
			||||||
 | 
					# fi
 | 
				
			||||||
@@ -0,0 +1,128 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to block unannotated tags from entering.
 | 
				
			||||||
 | 
					# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "update".
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# Config
 | 
				
			||||||
 | 
					# ------
 | 
				
			||||||
 | 
					# hooks.allowunannotated
 | 
				
			||||||
 | 
					#   This boolean sets whether unannotated tags will be allowed into the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletetag
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting tags will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.allowmodifytag
 | 
				
			||||||
 | 
					#   This boolean sets whether a tag may be modified after creation. By default
 | 
				
			||||||
 | 
					#   it won't be.
 | 
				
			||||||
 | 
					# hooks.allowdeletebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether deleting branches will be allowed in the
 | 
				
			||||||
 | 
					#   repository.  By default they won't be.
 | 
				
			||||||
 | 
					# hooks.denycreatebranch
 | 
				
			||||||
 | 
					#   This boolean sets whether remotely creating branches will be denied
 | 
				
			||||||
 | 
					#   in the repository.  By default this is allowed.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Command line
 | 
				
			||||||
 | 
					refname="$1"
 | 
				
			||||||
 | 
					oldrev="$2"
 | 
				
			||||||
 | 
					newrev="$3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Safety check
 | 
				
			||||||
 | 
					if [ -z "$GIT_DIR" ]; then
 | 
				
			||||||
 | 
						echo "Don't run this script from the command line." >&2
 | 
				
			||||||
 | 
						echo " (if you want, you could supply GIT_DIR then run" >&2
 | 
				
			||||||
 | 
						echo "  $0 <ref> <oldrev> <newrev>)" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
 | 
				
			||||||
 | 
						echo "usage: $0 <ref> <oldrev> <newrev>" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Config
 | 
				
			||||||
 | 
					allowunannotated=$(git config --bool hooks.allowunannotated)
 | 
				
			||||||
 | 
					allowdeletebranch=$(git config --bool hooks.allowdeletebranch)
 | 
				
			||||||
 | 
					denycreatebranch=$(git config --bool hooks.denycreatebranch)
 | 
				
			||||||
 | 
					allowdeletetag=$(git config --bool hooks.allowdeletetag)
 | 
				
			||||||
 | 
					allowmodifytag=$(git config --bool hooks.allowmodifytag)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# check for no description
 | 
				
			||||||
 | 
					projectdesc=$(sed -e '1q' "$GIT_DIR/description")
 | 
				
			||||||
 | 
					case "$projectdesc" in
 | 
				
			||||||
 | 
					"Unnamed repository"* | "")
 | 
				
			||||||
 | 
						echo "*** Project description file hasn't been set" >&2
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
						;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Check types
 | 
				
			||||||
 | 
					# if $newrev is 0000...0000, it's a commit to delete a ref.
 | 
				
			||||||
 | 
					zero="0000000000000000000000000000000000000000"
 | 
				
			||||||
 | 
					if [ "$newrev" = "$zero" ]; then
 | 
				
			||||||
 | 
						newrev_type=delete
 | 
				
			||||||
 | 
					else
 | 
				
			||||||
 | 
						newrev_type=$(git cat-file -t $newrev)
 | 
				
			||||||
 | 
					fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					case "$refname","$newrev_type" in
 | 
				
			||||||
 | 
						refs/tags/*,commit)
 | 
				
			||||||
 | 
							# un-annotated tag
 | 
				
			||||||
 | 
							short_refname=${refname##refs/tags/}
 | 
				
			||||||
 | 
							if [ "$allowunannotated" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** The un-annotated tag, $short_refname, is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								echo "*** Use 'git tag [ -a | -s ]' for tags you want to propagate." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,delete)
 | 
				
			||||||
 | 
							# delete tag
 | 
				
			||||||
 | 
							if [ "$allowdeletetag" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tag is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/tags/*,tag)
 | 
				
			||||||
 | 
							# annotated tag
 | 
				
			||||||
 | 
							if [ "$allowmodifytag" != "true" ] && git rev-parse $refname > /dev/null 2>&1
 | 
				
			||||||
 | 
							then
 | 
				
			||||||
 | 
								echo "*** Tag '$refname' already exists." >&2
 | 
				
			||||||
 | 
								echo "*** Modifying a tag is not allowed in this repository." >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,commit)
 | 
				
			||||||
 | 
							# branch
 | 
				
			||||||
 | 
							if [ "$oldrev" = "$zero" -a "$denycreatebranch" = "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Creating a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/heads/*,delete)
 | 
				
			||||||
 | 
							# delete branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,commit)
 | 
				
			||||||
 | 
							# tracking branch
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						refs/remotes/*,delete)
 | 
				
			||||||
 | 
							# delete tracking branch
 | 
				
			||||||
 | 
							if [ "$allowdeletebranch" != "true" ]; then
 | 
				
			||||||
 | 
								echo "*** Deleting a tracking branch is not allowed in this repository" >&2
 | 
				
			||||||
 | 
								exit 1
 | 
				
			||||||
 | 
							fi
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
						*)
 | 
				
			||||||
 | 
							# Anything else (is there anything else?)
 | 
				
			||||||
 | 
							echo "*** Update hook: unknown type of update to ref $refname of type $newrev_type" >&2
 | 
				
			||||||
 | 
							exit 1
 | 
				
			||||||
 | 
							;;
 | 
				
			||||||
 | 
					esac
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# --- Finished
 | 
				
			||||||
 | 
					exit 0
 | 
				
			||||||
@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					# git ls-files --others --exclude-from=.git/info/exclude
 | 
				
			||||||
 | 
					# Lines that start with '#' are comments.
 | 
				
			||||||
 | 
					# For a project mostly in C, the following would be a good set of
 | 
				
			||||||
 | 
					# exclude patterns (uncomment them if you want to use them):
 | 
				
			||||||
 | 
					# *.[oa]
 | 
				
			||||||
 | 
					# *~
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					bf19fd4707acb403c4aca44f126ab69142ac59ce
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ref: refs/heads/master
 | 
				
			||||||
@@ -0,0 +1,4 @@
 | 
				
			|||||||
 | 
					[core]
 | 
				
			||||||
 | 
						repositoryformatversion = 0
 | 
				
			||||||
 | 
						filemode = true
 | 
				
			||||||
 | 
						bare = true
 | 
				
			||||||
@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					Unnamed repository; edit this file 'description' to name the repository.
 | 
				
			||||||
@@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message taken by
 | 
				
			||||||
 | 
					# applypatch from an e-mail message.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# The hook should exit with non-zero status after issuing an
 | 
				
			||||||
 | 
					# appropriate message if it wants to stop the commit.  The hook is
 | 
				
			||||||
 | 
					# allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "applypatch-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					. git-sh-setup
 | 
				
			||||||
 | 
					commitmsg="$(git rev-parse --git-path hooks/commit-msg)"
 | 
				
			||||||
 | 
					test -x "$commitmsg" && exec "$commitmsg" ${1+"$@"}
 | 
				
			||||||
 | 
					:
 | 
				
			||||||
@@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# An example hook script to check the commit log message.
 | 
				
			||||||
 | 
					# Called by "git commit" with one argument, the name of the file
 | 
				
			||||||
 | 
					# that has the commit message.  The hook should exit with non-zero
 | 
				
			||||||
 | 
					# status after issuing an appropriate message if it wants to stop the
 | 
				
			||||||
 | 
					# commit.  The hook is allowed to edit the commit message file.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# To enable this hook, rename this file to "commit-msg".
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Uncomment the below to add a Signed-off-by line to the message.
 | 
				
			||||||
 | 
					# Doing this in a hook is a bad idea in general, but the prepare-commit-msg
 | 
				
			||||||
 | 
					# hook is more suited to it.
 | 
				
			||||||
 | 
					#
 | 
				
			||||||
 | 
					# SOB=$(git var GIT_AUTHOR_IDENT | sed -n 's/^\(.*>\).*$/Signed-off-by: \1/p')
 | 
				
			||||||
 | 
					# grep -qs "^$SOB" "$1" || echo "$SOB" >> "$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# This example catches duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test "" = "$(grep '^Signed-off-by: ' "$1" |
 | 
				
			||||||
 | 
						 sort | uniq -c | sed -e '/^[ 	]*1[ 	]/d')" || {
 | 
				
			||||||
 | 
						echo >&2 Duplicate Signed-off-by lines.
 | 
				
			||||||
 | 
						exit 1
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,7 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					ORI_DIR=`pwd`
 | 
				
			||||||
 | 
					SHELL_FOLDER=$(cd "$(dirname "$0")";pwd)
 | 
				
			||||||
 | 
					cd "$ORI_DIR"
 | 
				
			||||||
 | 
					for i in `ls "$SHELL_FOLDER/post-receive.d"`; do
 | 
				
			||||||
 | 
					    sh "$SHELL_FOLDER/post-receive.d/$i"
 | 
				
			||||||
 | 
					done
 | 
				
			||||||
@@ -0,0 +1,2 @@
 | 
				
			|||||||
 | 
					#!/usr/bin/env bash
 | 
				
			||||||
 | 
					"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive
 | 
				
			||||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user