github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/review/git-review/hook.go (about)

     1  // Copyright 2014 The Go Authors.  All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"runtime"
    12  )
    13  
    14  var hookFile = filepath.FromSlash(".git/hooks/commit-msg")
    15  
    16  func installHook() {
    17  	filename := filepath.Join(repoRoot(), hookFile)
    18  	_, err := os.Stat(filename)
    19  	if err == nil {
    20  		return
    21  	}
    22  	if !os.IsNotExist(err) {
    23  		dief("error checking for hook file: %v", err)
    24  	}
    25  	verbosef("Presubmit hook to add Change-Id to commit messages is missing.")
    26  	verbosef("Automatically creating it at %v.", filename)
    27  	hookContent := []byte(commitMsgHook)
    28  	if err := ioutil.WriteFile(filename, hookContent, 0700); err != nil {
    29  		dief("error writing hook file: %v", err)
    30  	}
    31  }
    32  
    33  func repoRoot() string {
    34  	dir, err := os.Getwd()
    35  	if err != nil {
    36  		dief("could not get current directory: %v", err)
    37  	}
    38  	rootlen := 1
    39  	if runtime.GOOS == "windows" {
    40  		rootlen += len(filepath.VolumeName(dir))
    41  	}
    42  	for {
    43  		if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
    44  			return dir
    45  		}
    46  		if len(dir) == rootlen && dir[rootlen-1] == filepath.Separator {
    47  			dief("git root not found. Rerun from within the Git tree.")
    48  		}
    49  		dir = filepath.Dir(dir)
    50  	}
    51  }
    52  
    53  var commitMsgHook = `#!/bin/sh
    54  # From Gerrit Code Review 2.2.1
    55  #
    56  # Part of Gerrit Code Review (http://code.google.com/p/gerrit/)
    57  #
    58  # Copyright (C) 2009 The Android Open Source Project
    59  #
    60  # Licensed under the Apache License, Version 2.0 (the "License");
    61  # you may not use this file except in compliance with the License.
    62  # You may obtain a copy of the License at
    63  #
    64  # http://www.apache.org/licenses/LICENSE-2.0
    65  #
    66  # Unless required by applicable law or agreed to in writing, software
    67  # distributed under the License is distributed on an "AS IS" BASIS,
    68  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    69  # See the License for the specific language governing permissions and
    70  # limitations under the License.
    71  #
    72  
    73  CHANGE_ID_AFTER="Bug|Issue"
    74  MSG="$1"
    75  
    76  # Check for, and add if missing, a unique Change-Id
    77  #
    78  add_ChangeId() {
    79  	clean_message=` + "`" + `sed -e '
    80  		/^diff --git a\/.*/{
    81  			s///
    82  			q
    83  		}
    84  		/^Signed-off-by:/d
    85  		/^#/d
    86  	' "$MSG" | git stripspace` + "`" + `
    87  	if test -z "$clean_message"
    88  	then
    89  		return
    90  	fi
    91  
    92  	if grep -i '^Change-Id:' "$MSG" >/dev/null
    93  	then
    94  		return
    95  	fi
    96  
    97  	id=` + "`" + `_gen_ChangeId` + "`" + `
    98  	perl -e '
    99  		$MSG = shift;
   100  		$id = shift;
   101  		$CHANGE_ID_AFTER = shift;
   102  
   103  		undef $/;
   104  		open(I, $MSG); $_ = <I>; close I;
   105  		s|^diff --git a/.*||ms;
   106  		s|^#.*$||mg;
   107  		exit unless $_;
   108  
   109  		@message = split /\n/;
   110  		$haveFooter = 0;
   111  		$startFooter = @message;
   112  		for($line = @message - 1; $line >= 0; $line--) {
   113  			$_ = $message[$line];
   114  
   115  			if (/^[a-zA-Z0-9-]+:/ && !m,^[a-z0-9-]+://,) {
   116  				$haveFooter++;
   117  				next;
   118  			}
   119  			next if /^[ []/;
   120  			$startFooter = $line if ($haveFooter && /^\r?$/);
   121  			last;
   122  		}
   123  
   124  		@footer = @message[$startFooter+1..@message];
   125  		@message = @message[0..$startFooter];
   126  		push(@footer, "") unless @footer;
   127  
   128  		for ($line = 0; $line < @footer; $line++) {
   129  			$_ = $footer[$line];
   130  			next if /^($CHANGE_ID_AFTER):/i;
   131  			last;
   132  		}
   133  		splice(@footer, $line, 0, "Change-Id: I$id");
   134  
   135  		$_ = join("\n", @message, @footer);
   136  		open(O, ">$MSG"); print O; close O;
   137  	' "$MSG" "$id" "$CHANGE_ID_AFTER"
   138  }
   139  _gen_ChangeIdInput() {
   140  	echo "tree ` + "`" + `git write-tree` + "`" + `"
   141  	if parent=` + "`" + `git rev-parse HEAD^0 2>/dev/null` + "`" + `
   142  	then
   143  		echo "parent $parent"
   144  	fi
   145  	echo "author ` + "`" + `git var GIT_AUTHOR_IDENT` + "`" + `"
   146  	echo "committer ` + "`" + `git var GIT_COMMITTER_IDENT` + "`" + `"
   147  	echo
   148  	printf '%s' "$clean_message"
   149  }
   150  _gen_ChangeId() {
   151  	_gen_ChangeIdInput |
   152  	git hash-object -t commit --stdin
   153  }
   154  
   155  
   156  add_ChangeId
   157  `