]> git.alsa-project.org Git - alsa.git/commitdiff
initial version
authorJaroslav Kysela <perex@perex.cz>
Fri, 30 May 2008 06:56:47 +0000 (08:56 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 30 May 2008 06:56:47 +0000 (08:56 +0200)
alsatool [new file with mode: 0755]
hooks/alsa-kernel.git/pre-receive [new file with mode: 0755]

diff --git a/alsatool b/alsatool
new file mode 100755 (executable)
index 0000000..ad46af3
--- /dev/null
+++ b/alsatool
@@ -0,0 +1,532 @@
+#! /usr/bin/python
+# -*- Python -*-
+
+"""HG ALSA Tool
+
+Do operations on ALSA GIT repositories.
+
+Usage:
+       %(PROGRAM)s [options] command
+"""
+
+import os
+import sys
+import getopt
+
+VERSION="2.0"
+
+PROGRAM = sys.argv[0]
+ROOT = os.path.abspath(os.getcwd())
+USER = os.getenv('USER')
+VERBOSE = False
+REPOSITORIES = [
+        'alsa', 'alsa-driver', 'alsa-kmirror', 'alsa-lib', 'alsa-utils',
+        'alsa-tools', 'alsa-firmware', 'alsa-oss', 'alsa-plugins',
+        'alsa-python'
+]        
+
+def eprint(msg):
+        sys.stderr.write(msg + '\n')
+
+def selectrepos(repos):
+        if repos == None or len(repos) == 0:
+                return REPOSITORIES[:]
+        else:
+               neg = repos[0][0] == '-'
+               for repo in repos:
+                       if (neg and repo[0] != '-') or \
+                          (not neg and repo[0] == '-'):
+                               raise ValueError, "inverted and non-inverted repo specifications cannot be mixed!"
+               if neg:
+                       res = REPOSITORIES
+                       for repo in repos:
+                               res.remove(repo[1:])
+                       return res
+               for repo in repos:
+                       if not repo in REPOSITORIES:
+                               raise ValueError, "repository '%s' is unknown" % repo
+                return repos
+
+def xlist(argv=None):
+       s = ''
+       for i in REPOSITORIES:
+               s += i + ' '
+       print s[:-1]
+
+def git(repo):
+       dir = ROOT + '/' + repo
+       return "git --work-tree=%s --git-dir=%s" % (dir, dir + '/.git')
+
+def clone(argv=None):
+        repos = selectrepos(argv)
+        for repo in repos:
+               print "clone", repo
+
+def diff(argv=None):
+        repos = selectrepos(argv)
+       for repo in repos:
+               pull([repo])
+               if os.system("%s --no-pager diff origin/master..master" % git(repo)):
+                       raise ValueError, "diff %s" % repo
+
+def pull(argv=None):
+        repos = selectrepos(argv)
+       for repo in repos:
+               if os.system("%s checkout master" % git(repo)):
+                       raise ValueError, "checkout %s" % repo
+               os.chdir(ROOT + '/' + repo)
+               if os.system("%s pull" % git(repo)):
+                       raise ValueError, "pull %s" % repo
+
+def push(argv=None):
+        repos = selectrepos(argv)
+       for repo in repos:
+               if os.system("%s checkout master" % git(repo)):
+                       raise ValueError, "checkout %s" % repo
+               if os.system("%s push master:refs/heads/master" % git(repo)):
+                       raise ValueError, "push %s" % repo
+
+def version_sort(tags):
+       tags1 = []
+       tags2 = {}
+       for tag in tags:
+               tag = tag.strip()
+               if tag == "tip":
+                       continue
+               try:
+                       a, b, c = tag.split('.')
+                       if a[0] != 'v':
+                               raise ValueError
+                       a = int(a[1:])
+                       b = int(b)
+                       idx = 0
+                       while idx < len(c) and ord(c[idx]) <= ord('9'):
+                               idx += 1
+                       c1 = int(c[:idx])
+                       c2 = c[idx:]
+                       str = "%08i.%08i.%08i.%s" % (a, b, c1, c2)
+                       tags1.append(str)
+                       tags2[str] = tag
+               except:
+                       from traceback import print_exc
+                       print_exc()
+                       pass
+       tags1.sort()
+       res = []
+       for tag in tags1:
+               res.append(tags2[tag])
+       if len(res) > 0:
+               return res
+       return None
+
+def showchanges1(repos):
+       res = {}
+       for repo in repos:
+               if repo == 'alsa':
+                       continue
+               res[repo] = []
+               tags = version_sort(os.popen("%s tag" % git(repo)).readlines())
+               if not tags:
+                       raise ValueError, "cannot obtain tags for repo %s" % repo
+               fp = os.popen("%s diff --stat %s..HEAD" % (git(repo), tags[-1]))
+               while 1:
+                       line = fp.readline()
+                       if not line or line.find('|') <= 0:
+                               break
+                       a, b = line.split('|')
+                       a = a.strip()
+                       if a in ['.hgignore', '.hgtags']:
+                               continue
+                       if a.endswith('.gitignore'):
+                               continue
+                       if VERBOSE:
+                               print ' ', line.strip()
+                       res[repo].append(a)
+               del fp
+       return res
+
+def showchanged(argv=None):
+        if argv == None:
+               tag = "last"
+               repos = selectrepos(None)
+       else:
+               tag = argv[0]
+               repos = selectrepos(argv[1:])
+       res = showchanges1(repos)
+       for repo in res:
+               print 'Repository %s has %s changed files' % (repo, len(res[repo]))
+               if VERBOSE:
+                       print ' ', line.strip()
+
+def release1(repo, tag):
+       print
+       print 'Repository %s' % repo
+       print ''.rjust(11 + len(repo), '*')
+       version = tag[1:]
+       pull([repo])
+       if repo == 'alsa-driver':
+               pull(['alsa-kmirror'])
+       if repo == 'alsa-driver':
+               lines = open(ROOT + '/' + repo + '/configure.in').readlines()
+               for idx in range(0, len(lines)):
+                       if lines[idx].startswith('CONFIG_SND_VERSION="'):
+                               lines[idx] = 'CONFIG_SND_VERSION="%s"\n' % version
+                               print lines[idx][:-1]
+                               break
+               open(ROOT + '/' + repo + '/configure.in', "w+").write(''.join(lines))
+               os.chdir(ROOT + '/' + repo)
+               if os.path.exists('include/version.h'):
+                       os.remove('include/version.h')
+               if os.path.exists('alsa-kernel/include/version.h'):
+                       os.remove('alsa-kernel/include/version.h')
+               if os.system("make ALSAKERNELDIR=../alsa-kernel all-deps"):
+                       raise ValueError, "make"
+               if os.system("aclocal"):
+                       raise ValueError, "aclocal"
+               if os.system("autoconf"):
+                       raise ValueError, "autoconf"
+               if os.system("./configure --with-debug=full --with-isapnp=yes --with-sequencer=yes --with-kernel=%s" % (ROOT + '/alsa-kernel')):
+                       raise ValueError, "configure"
+               if os.system("make include/sound/version.h"):
+                       raise ValueError, "include/sound/version.h"
+       elif repo in ['alsa-lib', 'alsa-plugins', 'alsa-utils',
+                     'alsa-firmware', 'alsa-oss']:
+               lines = open(ROOT + '/' + repo + '/configure.in').readlines()
+               for idx in range(0, len(lines)):
+                       if lines[idx].startswith('AM_INIT_AUTOMAKE(%s, ' % repo):
+                               lines[idx] = 'AM_INIT_AUTOMAKE(%s, %s)"\n' % (repo, version)
+                               print lines[idx][:-1]
+                               break
+               open(ROOT + '/' + repo + '/configure.in', "w+").write(''.join(lines))
+       elif repo == 'alsa-tools':
+               lines = open(ROOT + '/' + repo + '/Makefile').readlines()
+               for idx in range(0, len(lines)):
+                       if lines[idx].startswith("VERSION = "):
+                               lines[idx] = "VERSION = %s\n" % version
+                               print lines[idx][:-1]
+                               break
+               open(ROOT + '/' + repo + '/Makefile', "w+").write(''.join(lines))
+       elif repo == 'alsa-python':
+               lines = open(ROOT + '/' + repo + '/setup.py').readlines()
+               for idx in range(0, len(lines)):
+                       if lines[idx].startswith("VERSION='"):
+                               lines[idx] = "VERSION='%s'\n" % version
+                               print lines[idx][:-1]
+                               break
+               open(ROOT + '/' + repo + '/setup.py', "w+").write(''.join(lines))
+               lines = open(ROOT + '/' + repo + '/PKG-INFO').readlines()
+               for idx in range(0, len(lines)):
+                       if lines[idx].startswith("Version: "):
+                               lines[idx] = "Version: %s\n" % version
+                               print lines[idx][:-1]
+                               break
+               open(ROOT + '/' + repo + '/PKG-INFO', "w+").write(''.join(lines))
+
+def release(argv):
+       if argv == None or argv[0][0] != 'v':
+               raise ValueError, "specify release version in tag form"
+       tag = argv[0]
+       argv = argv[1:]
+       if len(argv) == 0:
+               repos = selectrepos(None)
+       elif argv[0] == 'auto':
+               res = showchanges1(selectrepos(None))
+               repos = res.keys()
+       else:
+               repos = selectrepos(argv)
+       if 'alsa' in repos:
+               repos.remove('alsa')
+       if 'alsa-kmirror' in repos:
+               repos.remove('alsa-kmirror')
+       print 'Doing release for: %s' % ','.join(repos)
+       for repo in repos:
+               release1(repo, tag)
+
+def changes(argv):
+        
+       def rev_to_dot(rev):
+               if rev[0] == 'v':
+                       return rev[1:]
+               else:
+                       return rev
+
+       def print_underline(c, str):
+               i = len(str)
+               while i > 0:
+                       sys.stdout.write(c)
+                       i -= 1
+               print
+
+        def store_changes(changes, logs, module, xrev):
+               if module == 'alsa-kernel':
+                       module = 'alsa-driver'
+                for a in logs:
+                        if a.has_key('branch'):
+                                return
+                       already = False
+                       idx1 = 0
+                       for change in changes:
+                               if a['user'] == change['user'] and \
+                                  a['description'] == change['description']:
+                                       # print 'SAME!!!'
+                                       already = True
+                                       break
+                               if a['date'] < change['date']:
+                                       a['xrev'] = xrev
+                                       a['module'] = module
+                                       changes.insert(idx1, a)
+                                       # print 'INSERTED!!!'
+                                       already = True
+                                       break
+                               idx1 += 1
+                       if not already:
+                               a['xrev'] = xrev
+                               a['module'] = module
+                               changes.append(a)
+
+        def merge_members(changes):
+               global GERRORS
+
+               res = {}
+               try:
+                       os.remove("/tmp/changes-log.txt")
+               except OSError:
+                       pass
+                for change in changes:
+                       module = change['module']
+                       if not res.has_key(module):
+                               res[module] = {}
+                        members = cvsps_merge_members(change['files'], module)
+                        if len(members) == 0:
+                               continue
+                       members = members[0]
+                       mems = string.split(members, ',')
+                       for mem in mems:
+                               if mem == 'IGNORE':
+                                       continue
+                               if not res[module].has_key(mem):
+                                       res[module][mem] = []
+                                res[module][mem].append(change)
+                        if GERRORS > 0:
+                                print 'Bailing out...'
+                                sys.exit(1);
+               return res
+
+        def get_items(allitems):
+               items = []
+               idx = 0
+               for item in ['Sound Core', 'ALSA Core']:
+                       items.append([item])
+                       idx += 1
+               core = idx
+               items.append([])        # Core
+               midlevel = idx + 1
+               items.append([])        # Midlevel
+               all = idx + 2
+               items.append(allitems)
+               items[all].sort()
+               for item in items[all]:
+                       if string.find(item, 'Core') >= 0:
+                               items[core].append(item)
+                       if string.find(item, 'Midlevel') >= 0:
+                               items[midlevel].append(item)
+                       if string.find(item, 'API') >= 0:
+                               items[midlevel].append(item)
+               idx1 = core
+               while idx1 < all:
+                       for item in items[idx1]:
+                               items[all].remove(item)
+                       idx1 += 1
+               for items1 in items[:idx]:
+                       for item in items1:
+                               idx1 = idx
+                               while idx1 < len(items):
+                                       if item in items[idx1]:
+                                               items[idx1].remove(item)
+                                       idx1 += 1
+               return items
+
+        def check_tag(tags, rev):
+                for tag in tags:
+                        a = tag[41:-1]
+                        if len(a) != len(rev):
+                                continue
+                        if a == rev:
+                                return True
+                return False
+
+       try:
+               rev1 = argv[0]
+               rev2 = argv[1]
+       except:
+               sys.stderr.write('Please, specify oldtag and newtag\n')
+               sys.exit(1)
+
+       changes = []
+       fullset = REPOSITORIES
+       fromrev = {}
+       for module in fullset:
+               xrev = rev1
+               fp = os.popen("%s tag" % git(module))
+               tags = fp.readlines()
+               fp.close()
+               if not check_tag(tags, rev2):
+                       continue
+                tags1 = []
+                base = rev2
+                while not check_tag(tags, xrev):
+                        if rev2[-3:-1] == "rc":
+                                base = rev2[:-3]
+                        elif rev2[-1:] >= "a":
+                                base = rev2[:-1]
+                        for tag in tags:
+                                a = tag[41:-1].strip()
+                               if a >= rev2:
+                                       continue
+                               tags1.append(tag[40:-1].strip())
+                        tags1 = version_sort(tags1)
+                        if len(tags1) != 0:
+                                xrev = tags1[len(tags1)-1]
+                                break
+                        major, minor, subminor = base.split('.')
+                        subminor = int(subminor) - 1
+                        if subminor < 0:
+                                raise ValueError
+                        base = "%s.%s.%s" % (major, minor, subminor)
+               fromrev[module] = xrev
+               lines = my_popen("hg log -r %s:%s -v" % (xrev, rev2))
+               store_changes(changes, parse_hg_log(lines, module), module, xrev)
+       res = merge_members(changes)
+       modules1 = res.keys()
+       modules = []
+       groups = {}
+       for module in fullset:
+               if module in modules1:
+                       modules.append(module)
+                       rev = fromrev[module]
+                       if not groups.has_key(rev):
+                               groups[rev] = []
+                       groups[rev].append(module)
+       print '{| align="right"\n| __TOC__\n|}'
+       for rev in groups:
+               str = '=Changelog between %s and %s releases=' % (rev_to_dot(rev), rev_to_dot(rev2))
+               print str
+               for module in groups[rev]:
+                       print '==%s==' % module
+                       items = get_items(res[module].keys())
+                       for items1 in items:
+                               for b in items1:
+                                       if not res[module].has_key(b):
+                                               continue
+                                       print '===%s===' % b
+                                       for a in res[module][b]:
+                                               log = a['description'][0]
+                                               if log[:9] == 'Summary: ':
+                                                       log = log[9:]
+                                               elif log[:8] == 'Summary:':
+                                                       log = log[8:]
+                                               print ': %s' % log[:-1]
+       for rev in groups:
+               str = '=Detailed changelog between %s and %s releases=' % (rev_to_dot(rev), rev_to_dot(rev2))
+               print str
+               for module in groups[rev]:
+                       print '==%s==' % module
+                       items = get_items(res[module].keys())
+                       for items1 in items:
+                               for b in items1:
+                                       if not res[module].has_key(b):
+                                               continue
+                                       print '===%s===' % b
+                                       for a in res[module][b]:
+                                               log = a['description']
+                                               first = "-"
+                                               for l in log:
+                                                       if l[:13] == "Patch-level: ":
+                                                               continue
+                                                       if l[:13] == "Patch-Level: ":
+                                                               continue
+                                                       print ': %s %s' % (first, l[:-1])
+                                                       first = " "
+
+def usage(code=0, msg=''):
+        print __doc__ % globals()
+        print 'Where options is:'
+        for opt in OPTS:
+                print
+                print "\t-%s %s" % (opt[0].replace(':', ''), opt[3])
+                print "\t--%s %s" % (opt[1].replace('=', ''), opt[3])
+                print "\t\t%s" % opt[4]
+        print
+        print 'Where command is:'
+        for cmd in CMDS:
+                print
+                print "\t%s %s" % (cmd[0], cmd[2])
+                print "\t\t%s" % cmd[3]
+        if msg:
+                print
+                print msg
+        sys.exit(code)
+
+def root(argv):
+       global ROOT
+        if argv == None:
+                eprint('Specify root directory.')
+                sys.exit(1)
+        ROOT=os.path.abspath(argv[0])
+
+def verbose(argv):
+       global VERBOSE
+       VERBOSE=True
+
+OPTS=[
+        ['h', 'help', usage, '', 'Print this help'],
+        ['r', 'root', root, '<GIT root dir>', 'Set GIT root directory (default is %s)' % ROOT],
+        ['v', 'verbose', verbose, '', 'Set verbose mode']
+]
+CMDS=[
+       ['list', xlist, '', 'Show ALSA repository names'],
+        ['clone', clone, '[repo]', 'Clone all (default) or selected repositories'],
+        ['diff', diff, '[repo]', 'Do diff on selected or all (default) repositories'],
+        ['pull', pull, '[repo]', 'Do pull on selected or all (default) repositories'],
+        ['push', push, '[repo]', 'Do push on selected or all (default) repositories'],
+        ['showchanged', showchanged, 'tag [repo]', 'Show which repositories were changed since tag'],
+        ['release', release, 'tag [repo]', 'Do an ALSA release (auto = automatic change control)'],
+        ['changes', changes, 'oldtag newtag', 'Show changes between oldtag and newtag']
+]
+def main():
+       global ROOT
+       if os.path.exists(ROOT + '/../alsa-kernel'):
+               ROOT = os.path.abspath(ROOT + '/..')
+        opts = ''
+        lopts = []
+        for opt in OPTS:
+              opts += opt[0]
+              lopt = opt[1]
+              if opt[3] != '':
+                      opts += ':'
+                      lopt += '='
+              lopts.append(lopt)
+        try:
+              opts, args = getopt.getopt(sys.argv[1:], opts, lopts)
+        except getopt.error, msg:
+                    usage(1, msg)
+        for opt, arg in opts:
+                for xopt in OPTS:
+                        if opt in ("-" + xopt[0], "-" + xopt[1]):
+                                xopt[2](arg)
+        if not args:
+              eprint("Command not specified, for help type '%s -h'" % PROGRAM[PROGRAM.rfind('/')+1:])
+              sys.exit(1)
+        for cmd in CMDS:
+              if cmd[0] == args[0]:
+                    if len(args) < 2:
+                          cmd[1]()
+                    else:
+                          cmd[1](args[1:])
+                    sys.exit(0)
+        usage(1, 'Unknown command "%s"' % args[0])
+
+if __name__ == '__main__':
+        main()
+        sys.exit(0)
diff --git a/hooks/alsa-kernel.git/pre-receive b/hooks/alsa-kernel.git/pre-receive
new file mode 100755 (executable)
index 0000000..7ea845b
--- /dev/null
@@ -0,0 +1,410 @@
+#!/usr/bin/python
+
+from sys import exit, stdin, stderr, stdout
+from os import popen, mkdir, system, chdir, getcwd, remove
+from os.path import isdir, exists
+from shutil import rmtree
+import re
+
+TMP_PATH = '/dev/shm'
+
+REPO_DIR = '/home/alsa-server/home/repositories'
+KMIRROR_REPO = REPO_DIR + '/alsa-kmirror.git'
+KERNEL_REPO = REPO_DIR + '/alsa-kernel.git'
+
+VALID_COMMITERS = (
+    'Jaroslav Kysela <perex@perex.cz>',
+    'Takashi Iwai <tiwai@suse.de>',
+    'Clemens Ladisch <clemens@ladisch.de>',
+    'James Courtier-Dutton <James@superbug.demon.co.uk>',
+    'Linus Torvalds <torvalds@linux-foundation.org>',
+)
+
+ALSA_FILES = (
+    'Documentation/sound/alsa/',
+    'sound/',
+    'include/sound/'
+)
+
+NOT_ALSA_FILES = (
+    'sound/sound_core.c',
+    'sound/sound_firmware.c',
+    'sound/oss/',
+)
+
+ALSA_FILES1 = {
+    'Documentation/sound/alsa/':       'Documentation/',
+    'sound/':                          '',
+    'include/sound/':                  'include/'
+}
+
+ALSA_COMMITS = {}
+ALSA_OK_COMMITS = []
+ALSA_LAST_COMMIT = ''
+UPSTREAM_COMMITS = []
+
+def error(lines, msg, *args):
+    for line in lines:
+      stderr.write('===> %s' % line)
+    stderr.write('PRE-RECEIVE ERROR: ' + msg % args)
+
+def fail(): 
+    if ALSA_LAST_COMMIT:
+        stderr.write('PRE-RECEIVE: Reverting alsa-kmirror.git repo to original state\n')
+        if system('git --git-dir=%s update-ref HEAD "refs/heads/master"' % KMIRROR_REPO):
+            raise ValueError, "update-ref failed"
+        if system('git --git-dir=%s reset -q --mixed %s > /dev/null' % (KMIRROR_REPO, ALSA_LAST_COMMIT)):
+            raise ValueError, "reset failed"
+    exit(1)
+
+def is_alsa_file(file):
+    for i in NOT_ALSA_FILES:
+        if file.startswith(i):
+            return False
+    for i in ALSA_FILES:
+        if file.startswith(i):
+            return True
+    return False
+
+def to_alsa_file(gitfile, prefix=''):
+    if gitfile == '/dev/null':
+        return '/dev/null'
+    if prefix and gitfile.startswith(prefix):
+        gitfile = gitfile[len(prefix):]
+    for i in ALSA_FILES1:
+        if gitfile.startswith(i):
+            return prefix + ALSA_FILES1[i] + gitfile[len(i):]
+    raise ValueError, repr(gitfile)
+
+def check_email(lines, fullemail, commit = False):
+    #print 'E-mail: "%s"' % fullemail
+    name, email = fullemail.split('<')
+    name = name.strip()
+    email = email.strip()
+    if not email.endswith('>'):
+        error(lines, 'E-mail address "%s" is not valid...\n' % (line))
+        return False
+    email = email[:-1]
+    if email.find('@') <= 0 or len(name) < 5 or fullemail.find('root@') >= 0:
+        error(lines, 'E-mail address "%s" is not valid...\n' % (line))
+        return False
+    if not commit:
+        return True
+    full = name + ' <' + email + '>'
+    if not full in VALID_COMMITERS:
+      error(lines, 'Commiter "%s" e-mail unknown. We know only these committers:\n' % full)
+      for line in VALID_COMMITERS:
+        stderr.write('***** %s\n' % line)
+      return False
+    return True
+
+def read_kmirror_commits():
+    global ALSA_LAST_COMMIT
+    if ALSA_COMMITS:
+        return
+    stderr.write('PRE-RECEIVE: Analyzing alsa-kmirror commits\n')
+    fp = popen("git --git-dir=%s log --pretty=fuller --date=iso" % KMIRROR_REPO)
+    commitref = ''
+    commit = {}
+    while 1:
+        line = fp.readline()
+        if not line:
+            break
+        if line.startswith('commit '):
+            if commitref:
+                ALSA_COMMITS[commitref] = commit
+                commit = {}
+            commitref = line[7:].strip()
+            if not ALSA_LAST_COMMIT:
+                ALSA_LAST_COMMIT = commitref
+        elif line.startswith('Author:') or line.startswith('AuthorDate:') or \
+             line.startswith('Commit:') or line.startswith('CommitDate:'):
+            a, b = line.split(': ')
+            commit[a.strip()] = b.strip()
+    if commitref:
+        ALSA_COMMITS[commitref] = commit
+    fp.close()
+
+    worktree = TMP_PATH + '/alsa-kmirror-repo'
+    rmtree(worktree, ignore_errors=True)
+    mkdir(worktree)
+    if system("git --work-tree=%s --git-dir=%s checkout -q master scripts" % (worktree, KMIRROR_REPO)):
+        raise ValueError, 'git checkout'
+    if exists(worktree + '/scripts/git-ok-commits'):
+        fp = open(worktree + '/scripts/git-ok-commits')
+        while 1:
+            line = fp.readline()
+            if not line:
+                break
+            if line.startswith('#'):
+                continue
+            ALSA_OK_COMMITS.append(line.strip())
+    fp.close()
+    rmtree(worktree, ignore_errors=True)
+
+def check_alsa_commit(commit):
+    subject = commit['comment'][0][:-1]
+    if not ALSA_COMMITS:
+        read_kmirror_commits()
+    for c in ALSA_COMMITS:
+        if ALSA_COMMITS[c]['AuthorDate'] == commit['AuthorDate'] and \
+           ALSA_COMMITS[c]['Author'] == commit['Author'] and \
+           ALSA_COMMITS[c]['CommitDate'] == commit['CommitDate'] and \
+           ALSA_COMMITS[c]['Commit'] == commit['Commit']:
+             stderr.write('PRE-RECEIVE: Already merged %s %s\n' % (commit['commit'][:7], subject))
+             return True
+    okstr = '"' + commit['Author'] + '" "' + commit['AuthorDate'] + '" "' + commit['Commit'] + '" "' + commit['CommitDate'] + '"'
+    if okstr in ALSA_OK_COMMITS:
+       stderr.write('PRE-RECEIVE: Already merged (manually) %s %s\n' % (commit['commit'][:7], subject))
+       return True
+    return False
+
+def read_upstream_commits(old):
+    stderr.write('PRE-RECEIVE: Analyzing alsa-kernel#linux-2.6 commits\n')
+    head = popen("git rev-parse linux-2.6").readline().strip()
+    stderr.write('PRE-RECEIVE: linux-2.6 head %s old %s\n' % (head, old))
+    if head == old:
+        return
+    fp = popen("git log --pretty=oneline --date=iso %s..%s" % (old, head))
+    while 1:
+        line = fp.readline()
+        if not line:
+            break
+        a = line.split(' ')
+        UPSTREAM_COMMITS.append(a[0])
+    del fp
+    stderr.write('PRE-RECEIVE: linux-2.6 has %s new commits\n' % len(UPSTREAM_COMMITS))
+
+def try_to_merge(commit):
+    stderr.write('PRE-RECEIVE: Merging %s %s' % (commit['commit'][:7], commit['comment'][0]))
+
+    ref = commit['commit']
+    fp = popen("git diff %s~1..%s" % (ref, ref))
+    rlines = []
+    ok = False
+    addfiles = []
+    rmfiles = []
+    while 1:
+        line = fp.readline()
+        if not line:
+            break
+        if line.startswith('diff --git a/'):
+            file1, file2 = line[11:].split(' ')
+            file1 = file1.strip()
+            file2 = file2.strip()
+            ok1 = is_alsa_file(file1[2:])
+            ok2 = is_alsa_file(file2[2:])
+            if ok1 or ok2:
+                afile1 = to_alsa_file(file1, 'a/')
+                afile2 = to_alsa_file(file2, 'b/')
+                rlines.append('diff --git %s %s\n' % (afile1, afile2))
+                if ok2:
+                    addfiles.append(afile2[2:])
+                elif ok1:
+                    rmfiles.append(afile1[2:])
+                ok = True
+        elif ok and (line.startswith('--- a/') or line.startswith('+++ b/')):
+            rlines.append(line[:6] + to_alsa_file(line[6:].strip()) + '\n')
+        elif ok:
+            rlines.append(line)
+    fp.close()
+
+    patchfile = TMP_PATH + '/alsa-kmirror-patch'
+    fp = open(patchfile, 'w+')
+    fp.write(''.join(rlines))
+    fp.close()
+
+    commentfile = TMP_PATH + '/alsa-kmirror-comment'
+    fp = open(commentfile, 'w+')
+    fp.write(''.join(commit['comment']))
+    fp.close()
+
+    elems = re.compile('(.*?)\s+<(.*)>').match(commit['Author'])
+    exports = 'export GIT_AUTHOR_NAME="%s" ; ' % elems.group(1)
+    exports += 'export GIT_AUTHOR_EMAIL="%s" ; ' % elems.group(2)
+    exports += 'export GIT_AUTHOR_DATE="%s" ; ' % commit['AuthorDate']
+    elems = re.compile('(.*?)\s+<(.*)>').match(commit['Commit'])
+    exports += 'export GIT_COMMITER_NAME="%s" ; ' % elems.group(1)
+    exports += 'export GIT_COMMITER_EMAIL="%s" ; ' % elems.group(2)
+    exports += 'export GIT_COMMITER_DATE="%s" ; ' % commit['CommitDate']
+    exports += 'export GIT_COMMITTER_NAME="%s" ; ' % elems.group(1)
+    exports += 'export GIT_COMMITTER_EMAIL="%s" ; ' % elems.group(2)
+    exports += 'export GIT_COMMITTER_DATE="%s" ; ' % commit['CommitDate']
+
+    curdir = getcwd()
+    worktree = TMP_PATH + '/alsa-kmirror-repo'
+    rmtree(worktree, ignore_errors=True)
+    mkdir(worktree)
+    if system("git --work-tree=%s --git-dir=%s checkout -f -q master" % (worktree, KMIRROR_REPO)):
+        raise ValueError, 'git checkout'
+    chdir(worktree)
+    if system("patch -p 1 --dry-run < %s" % patchfile):
+        chdir(curdir)
+        error(rlines, "Patch failed - is it already merged?\n")
+        error([], "You may consider to add this commit to alsa-kmirror.git/scripts/git-ok-commits .\n")
+        error([], "Please, check if patch was merged to alsa-kmirror.git at first!\n")
+        error([], 'line: "%s" "%s" "%s" "%s"\n' % (commit['Author'], commit['AuthorDate'], commit['Commit'], commit['CommitDate']))
+        fail()
+    if system("git --work-tree=%s --git-dir=%s apply -v %s" % (worktree, KMIRROR_REPO, patchfile)):
+        chdir(curdir)
+        raise ValueError, 'git apply' 
+    if addfiles and system("git --work-tree=%s --git-dir=%s add %s" % (worktree, KMIRROR_REPO, ' '.join(addfiles))):
+        chdir(curdir)
+        raise ValueError, 'git add' 
+    if rmfiles and system("git --work-tree=%s --git-dir=%s rm %s" % (worktree, KMIRROR_REPO, ' '.join(rmfiles))):
+        chdir(curdir)
+        raise ValueError, 'git rm' 
+    if system("%sgit --work-tree=%s --git-dir=%s commit -F %s" % (exports, worktree, KMIRROR_REPO, commentfile)):
+        chdir(curdir)
+        raise ValueError, 'git commit' 
+    chdir(curdir)
+    rmtree(worktree, ignore_errors=True)
+    stderr.write('PRE-RECEIVE: Merge complete %s %s' % (ref[:7], commit['comment'][0]))
+
+def do_check_commit(lines):
+    alsafiles = 0
+    otherfiles = 0
+    header = True
+    commit = {'comment':[], 'files':[]}
+    for line in lines:
+        if header:
+            if line.startswith('commit '):
+                commit['commit'] = line[7:].strip()
+            elif line.startswith('Merge:') or line.startswith('Author:') or \
+                 line.startswith('AuthorDate:') or line.startswith('Commit:') or \
+                 line.startswith('CommitDate:'):
+                a, b = line.split(': ')
+                commit[a.strip()] = b.strip()
+            elif line.startswith('    '):
+                header = False
+        if line.startswith('    '):
+            commit['comment'].append(line[4:])
+        elif not header and line != '\n':
+            commit['files'].append(line[:-1])
+            check = is_alsa_file(line[:-1])
+            if check:
+                alsafiles += 1
+            else:
+                otherfiles += 1
+    while commit['comment'][-1] == '\n':
+        del commit['comment'][-1]
+    if not alsafiles:
+        return
+    if check_alsa_commit(commit):
+        return
+    try_to_merge(commit)
+    if commit['commit'] in UPSTREAM_COMMITS:
+        stderr.write('PRE-RECEIVE: Upstream patch %s %s\n' % (commit['commit'][:7], lines[6][4:]))
+        return
+    if otherfiles:
+        stderr.write('PRE-RECEIVE: ALSA files %s other files %s\n' % (alsafiles, otherfiles))
+        return
+    if not check_email(lines, commit['Author']) or \
+       not check_email(lines, commit['Commit']):
+        fail()
+    #if not check_email(lines, committer, commit=True):
+    #    exit(1)
+    if not lines[6][4:].upper().startswith('[ALSA] ') and \
+       not lines[6][4:].upper().startswith('ALSA: '):
+        error(lines, 'First log line does not start with "[ALSA] "\n')
+        fail()
+    lastsigned = ''
+    for line in lines[6:]:
+        if not line.startswith('    '):
+            break
+        line = line[4:-1]
+        line1 = line.lower()
+        if line1.startswith('signed-off-by:'):
+            if not line.startswith('Signed-off-by:'):
+                error(lines, 'Wrong Signed-off-by: line: "%s"\n' % line)
+                fail()
+            lastsigned = line[15:].strip()
+    if not lastsigned:
+        error(lines, 'Commit has no Signed-off-by: line\n')
+        fail()
+    if not lastsigned in VALID_COMMITERS:
+        error(lines, 'Last Signed-off-by: line has an invalid ALSA committer\n')
+        fail()
+    
+def do_check(sha1old, sha1new, refname):
+    lines = popen("git log --reverse --name-only --pretty=fuller --date=iso %s..%s" % (sha1old, sha1new)).readlines()
+    count = len(lines)
+    idx = 1
+    while idx < count:
+        oldidx = idx - 1
+        commit = []
+        while idx < count and not lines[idx].startswith('commit '):
+            idx += 1
+        do_check_commit(lines[oldidx:idx])
+        idx += 1
+
+def compare_trees(lastref):
+    stderr.write('PRE-RECEIVE: comparing alsa-kmirror (old) and alsa-kernel (new) repos\n')
+    worktree = TMP_PATH + '/alsa-kmirror-repo'
+    worktreek = TMP_PATH + '/alsa-kernel-repo'
+    rmtree(worktree, ignore_errors=True)
+    rmtree(worktreek, ignore_errors=True)
+    mkdir(worktree)
+    mkdir(worktreek)
+    if system("git --work-tree=%s --git-dir=%s checkout -f -q master" % (worktree, KMIRROR_REPO)):
+        raise ValueError, 'git checkout (kmirror)'
+    if system("git --work-tree=%s --git-dir=%s checkout -q %s sound include/sound Documentation/sound/alsa" % (worktreek, KERNEL_REPO, lastref)):
+        raise ValueError, 'git checkout (kernel)'
+    curdir = getcwd()
+    chdir(TMP_PATH)
+    system("mv alsa-kernel-repo/sound/* alsa-kernel-repo")
+    rmtree("alsa-kernel-repo/sound")
+    system("mv alsa-kernel-repo/include/sound/* alsa-kernel-repo/include")
+    rmtree("alsa-kernel-repo/include/sound")
+    system("mv alsa-kernel-repo/Documentation/sound/alsa/* alsa-kernel-repo/Documentation")
+    rmtree("alsa-kernel-repo/Documentation/sound")
+    for i in ['.git-ok-commits', '.hgignore', '.hgtags', '.gitignore', 'kernel', 'scripts', 'oss']:
+        if isdir("alsa-kmirror-repo/%s" % i):
+            rmtree("alsa-kmirror-repo/%s" % i)
+        elif exists("alsa-kmirror-repo/%s" % i):
+            remove("alsa-kmirror-repo/%s" % i)
+    for i in ['oss']:
+        if isdir("alsa-kernel-repo/%s" % i):
+            rmtree("alsa-kernel-repo/%s" % i)
+        elif exists("alsa-kernel-repo/%s" % i):
+            remove("alsa-kernel-repo/%s" % i)
+    fp = popen("diff -ruNp alsa-kmirror-repo alsa-kernel-repo")
+    notempty = False
+    while 1:
+        line = fp.readline()
+        if not line:
+            break
+        stderr.write(line)
+        notempty = True
+    if notempty:
+        stderr.write('\n')
+    rmtree(worktree, ignore_errors=True)
+    rmtree(worktreek, ignore_errors=True)
+    if notempty:
+        stderr.write('PRE-RECEIVE: repositories does not match, please, fix it\n')
+        fail()
+
+lines = stdin.readlines()
+read_upstream_commits(lines[0][:-1].split(' ')[0])
+lastref = ''
+for line in lines:
+    sha1old, sha1new, refname = line[:-1].split(' ')
+    if refname in ['refs/heads/linux-2.6', 'refs/heads/for-linus']:
+        continue
+    elif refname.startswith('refs/tags/') or \
+         refname.startswith('refs/heads/private-') or \
+         refname.startswith('refs/heads/stable-2.6.'):
+        continue
+    elif refname != 'refs/heads/master':
+        stderr.write('PRE-RECEIVE: invalid branch "%s"\n' % refname)
+        fail()
+    do_check(sha1old, sha1new, refname)
+    lastref = sha1new
+if lastref:
+    compare_trees(lastref)
+    stderr.write('PRE-RECEIVE: Trees match...\n')
+stderr.write('PRE-RECEIVE: All done\n')
+if 0:
+    stderr.write('PRE-RECEIVE: Test mode active (try later)...\n')
+    fail()
+exit(0)