From: Eric S. Raymond Date: Tue, 2 Oct 2012 16:07:08 +0000 (-0400) Subject: git irkerhook is now called from update. X-Git-Tag: 1.4~2 X-Git-Url: http://git.tremily.us/gitweb.cgi?a=commitdiff_plain;h=be3a02506b563edee8cfe36b1fd5e1dfe95dc12a;p=irker.git git irkerhook is now called from update. This is required in order to correctly handle pushes of non-default branches to a bare repo. --- diff --git a/NEWS b/NEWS index 9f68da3..50feb14 100644 --- a/NEWS +++ b/NEWS @@ -25,6 +25,7 @@ Graceful handling of server disconnects and kicks. Distribution now inclues an installable irkerd plist for Mac OS/X. The color variable is no longer boolean; may be miRC or ANSI. + The installation instructions for irkerhook.py have changed! diff --git a/install.txt b/install.txt index 0602ad4..4666a6b 100644 --- a/install.txt +++ b/install.txt @@ -39,34 +39,9 @@ installed to launch irkerd as a boot-time service on that system. == Installing irkerhook.py == -irkerhook.py should be called from the post-commit hook of each -repository. See its header comment for detailed installation -instructions. - -You should set the server and (for Subversion) repository variables -from the command line in your post-commit hook. The server variable -should be set to the inside-the-firewall host running your irker -instance. - -A git invocation line should look something like this: - -/usr/local/bin/irkerhook.py server=internal.foobar.net - -Each project will be able to set its own channel URLs, provided it -has access to its git config file. - -A Subversion invocation should look something like this: - -REPOSITORY=$1 -REV=$2 -irkerhook.py repository=$REPOSITORY commit=$REV server=internal.foobar.net - -Note that unless you supply additional overrides of project= and -channels= in the hook, the basename of the repository will be used as -the project name and will also be used as the IRC channel name on -freenode. This is not a limitation of irker.irkerhook, but a -result of the absence of a git-config equivalent that the hook can -mine stuff out of. +Under git, a call to irkerhook.py should be installed in the update +hook script of your repo. Under Subversion, the call goes in your +repo's post-commit script. See the irkerhook manual page for details. == Testing == diff --git a/irkerhook.py b/irkerhook.py index 33da10f..eaf9f00 100755 --- a/irkerhook.py +++ b/irkerhook.py @@ -147,8 +147,8 @@ class GenericExtractor: "Make command-line overrides possible." for tok in self.arguments: for key in self.__dict__: - if tok.startswith(key + "="): - val = tok[len(key)+1:] + if tok.startswith("--" + key + "="): + val = tok[len(key)+3:] setattr(self, key, val) for (key, val) in self.__dict__.items(): if key in GenericExtractor.booleans: @@ -181,7 +181,8 @@ class GitExtractor(GenericExtractor): self.template = '%(bold)s%(project)s:%(reset)s %(green)s%(author)s%(reset)s %(repo)s:%(yellow)s%(branch)s%(reset)s * %(bold)s%(rev)s%(reset)s / %(bold)s%(files)s%(reset)s: %(logmsg)s %(brown)s%(url)s%(reset)s' self.color = do("git config --get irker.color") self.urlprefix = do("git config --get irker.urlprefix") or "gitweb" - # This one is git-specific + # These are git-specific + self.refname = do("git symbolic-ref HEAD 2>/dev/null") self.revformat = do("git config --get irker.revformat") # The project variable defaults to the name of the repository toplevel. if not self.project: @@ -201,13 +202,10 @@ class GitExtractor(GenericExtractor): here = os.path.dirname(here) # Get overrides self.do_overrides() - def commit_factory(self, _id): - commit = Commit(self, _id) + def commit_factory(self, commit_id): "Make a Commit object holding data for a specified commit ID." - # FIXME: Next two lines will have to change soon - refname = do("git symbolic-ref HEAD 2>/dev/null") - commit.commit = do("git rev-parse HEAD") - commit.branch = os.path.basename(refname) + commit = Commit(self, commit_id) + commit.branch = os.path.basename(self.refname) # Compute a description for the revision if self.revformat == 'raw': commit.rev = commit.commit @@ -236,19 +234,19 @@ class SvnExtractor(GenericExtractor): "Metadata extraction for the svn version control system." def __init__(self, arguments): GenericExtractor.__init__(self, arguments) - self.id = None # Some things we need to have before metadata queries will work + self.repository = None for tok in arguments: - if tok.startswith("repository="): - self.repository = tok[11:] + if tok.startswith("--repository="): + self.repository = tok[13:] self.project = os.path.basename(self.repository) self.template = '%(bold)s%(project)s%(reset)s: %(green)s%(author)s%(reset)s %(repo)s * %(bold)s%(rev)s%(reset)s / %(bold)s%(files)s%(reset)s: %(logmsg)s %(brown)s%(url)s%(reset)s' self.urlprefix = "viewcvs" self.load_preferences(os.path.join(self.repository, "irker.conf")) self.do_overrides() - def commit_factory(self, id): - self.id = id - commit = Commit(self, id) + def commit_factory(self, commit_id): + self.id = commit_id + commit = Commit(self, commit_id) commit.branch = "" commit.rev = "r%s" % self.id commit.author = self.svnlook("author") @@ -259,84 +257,79 @@ class SvnExtractor(GenericExtractor): return do("svnlook %s %s --revision %s" % (shellquote(info), shellquote(self.repository), shellquote(self.id))) if __name__ == "__main__": - import getopt - - try: - (options, arguments) = getopt.getopt(sys.argv[1:], "nV") - except getopt.GetoptError, msg: - print "irkerhook.py: " + str(msg) - raise SystemExit, 1 - notify = True - channels = "" - commit = "" - repository = "" - for (switch, val) in options: - if switch == '-n': + repository = None + refname = None + commits = [] + for arg in sys.argv[1:]: + if arg == '-n': notify = False - elif switch == '-V': + elif arg == '-V': print "irkerhook.py: version", version sys.exit(0) - - # Gather info for repo type discrimination - for tok in arguments: - if tok.startswith("repository="): - repository = tok[11:] - if tok.startswith("commit="): - commit = tok[7:] + elif arg.startswith("--refname="): + refname = arg[10:] + elif arg.startswith("--repository="): + repository = arg[13:] + elif not arg.startswith("--"): + commits.append(arg) # Determine the repository type. Default to git unless user has pointed # us at a repo with identifiable internals. vcs = "git" - if os.path.exists(os.path.join(repository, "format")): + if repository and os.path.exists(os.path.join(repository, "format")): vcs = "svn" # Someday we'll have extractors for several version-control systems if vcs == "svn": - if commit is None or repository is None: - sys.stderr.write("irkerhook: svn requires 'repository' and 'commit' variables.") + if repository is None or not commits: + sys.stderr.write("irkerhook: svn requires a repository and a commit.") sys.exit(1) - extractor = SvnExtractor(arguments) + extractor = SvnExtractor(sys.argv[1:]) else: - extractor = GitExtractor(arguments) - metadata = extractor.commit_factory(commit) + extractor = GitExtractor(sys.argv[1:]) + if not commits: + commits = [do("git rev-parse HEAD")] - # Message reduction. The assumption here is that IRC can't handle - # lines more than 510 characters long. If we exceed that length, we - # try knocking out the file list, on the theory that for notification - # purposes the commit text is more important. If it's still too long - # there's nothing much can be done other than ship it expecting the IRC - # server to truncate. - privmsg = str(metadata) - if len(privmsg) > 510: - metadata.files = "" + for commit in commits: + metadata = extractor.commit_factory(commit) + + # Message reduction. The assumption here is that IRC can't handle + # lines more than 510 characters long. If we exceed that length, we + # try knocking out the file list, on the theory that for notification + # purposes the commit text is more important. If it's still too long + # there's nothing much can be done other than ship it expecting the IRC + # server to truncate. privmsg = str(metadata) + if len(privmsg) > 510: + metadata.files = "" + privmsg = str(metadata) - # Anti-spamming guard. - channel_list = extractor.channels.split(",") - if extractor.maxchannels != 0: - channel_list = channel_list[:extractor.maxchannels] + # Anti-spamming guard. + channel_list = extractor.channels.split(",") + if extractor.maxchannels != 0: + channel_list = channel_list[:extractor.maxchannels] - # Ready to ship. - message = json.dumps({"to":channel_list, "privmsg":privmsg}) - if not notify: - print message - else: - try: - if extractor.tcp: - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((extractor.server or default_server, IRKER_PORT)) - sock.sendall(message + "\n") - finally: - sock.close() - else: - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - sock.sendto(message + "\n", (extractor.server or default_server, IRKER_PORT)) - finally: - sock.close() - except socket.error, e: - sys.stderr.write("%s\n" % e) + # Ready to ship. + message = json.dumps({"to":channel_list, "privmsg":privmsg}) + if not notify: + print message + else: + try: + if extractor.tcp: + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((extractor.server or default_server, IRKER_PORT)) + sock.sendall(message + "\n") + finally: + sock.close() + else: + try: + sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + sock.sendto(message + "\n", (extractor.server or default_server, IRKER_PORT)) + finally: + sock.close() + except socket.error, e: + sys.stderr.write("%s\n" % e) #End diff --git a/irkerhook.xml b/irkerhook.xml index 67e043c..914e3a7 100644 --- a/irkerhook.xml +++ b/irkerhook.xml @@ -20,7 +20,8 @@ irkerhook.py -n -V - variable=value + --variable=value + commit-id @@ -45,7 +46,7 @@ variables, variables with the prefix "irker.". In other VCSes, a configuration file, "irker.conf", in the repository's internals directory. Command-line arguments of the form -variable=value. +--variable=value. The following variables are general to all supported VCSes: @@ -145,10 +146,38 @@ a value less than 2, however, would probably be unwise. git -Under git, irkerhook.py does not -require any arguments. Preferences may be set in the repo -config file in an [irker] section. Here -is an example of what that can look like: +irkerhook.py + +Under git, the normal way to invoke this hook (from within the +update hook) passes with a refname followed by a list of commits. Because +git rev-list normally lists from most recent to oldest, +you'll want to use --reverse to make notifications be omitted in chronological +order. In a normal update script, the invocation should look like this + + +refname=$1 +old=$2 +new=$3 +irkerhook.py --refname=${refname} $(git rev-list --reverse ${old}..${new}) + + +except that you'll need an absolute path for irkerhook.py. + +For testing purposes and backward compatibility, if you invoke +irkerhook.py with no arguments (as in a +post-commit hook) it will behave as though it had been called like +this: + + +irkerhook.py --refname=refs/heads/master HEAD + + +However, this will not give the right result when you push to +a non-default branch of a bare repo. + +Preferences may be set in the repo config +file in an [irker] section. Here is an example of what that can look +like: [irker] @@ -157,10 +186,9 @@ is an example of what that can look like: channels = {irc://chat.freenode.net/gpsd, irc://chat.freenode.net/commits} -Command-line variable=value arguments are accepted but not -required. No attempt is made to interpret an -irker.conf file. You should not set the -"repository" variable (an equivalent will be computed). + You should not set the "repository" variable (an equivalent +will be computed). No attempt is made to interpret an +irker.conf file. The default value of the "project" variable is the basename of the repository directory. The default value of the "urlprefix" @@ -198,15 +226,17 @@ gives its post-commit hook. Thus, a typical invocation in the post-commit script will look like this: -irkerhook.py repository=$1 commit=$2 +REPO=$1 +REV=$2 +irkerhook.py --repository=$REPO $REV -Other variable=value settings may also be +Other --variable=value settings may also be given on the command line, and will override any settings in an irker.conf file. The default for the project variable is the basename of the -(required) repository= argument.The default value of the "urlprefix" +(required) --repository argument.The default value of the "urlprefix" variable is "viewcvs". If an irker.conf file exists in the repository @@ -221,7 +251,7 @@ channels = irc://chat.freenode/irker,irc://chat.freenode/commits tcp = false -Don't the "repository" or "commit" variables in this file; +Don't set the "repository" or "commit" variables in this file; that would have unhappy results. There are no Subversion-specific variables.