From 486ee0ed016978b5d01569a2ba7c9b12be5ce340 Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Mon, 1 Jun 2009 12:05:51 +0200 Subject: [PATCH] reworked alsatool git merging code Signed-off-by: Jaroslav Kysela --- alsatool | 2144 +++++++++++++---------------- comments.py | 13 + config.py | 34 + drivermerge.py | 400 ++++++ hooks/alsa-kernel.git/pre-receive | 471 ------- kernel-sync/git-ok-commits | 845 ------------ utils.py | 162 +++ 7 files changed, 1565 insertions(+), 2504 deletions(-) create mode 100644 config.py create mode 100644 drivermerge.py delete mode 100755 hooks/alsa-kernel.git/pre-receive delete mode 100644 kernel-sync/git-ok-commits create mode 100644 utils.py diff --git a/alsatool b/alsatool index 200eb22..6784705 100755 --- a/alsatool +++ b/alsatool @@ -13,1088 +13,835 @@ import os import sys import getopt import re +import config from shutil import rmtree, copyfile from rfc822 import parsedate_tz +from utils import git_repo, git_system, git_popen, diff_compare, \ + git_read_commits, raw_subject, eprint, tmpdir, package +from drivermerge import analyze_diff, driver_merge, compare_trees from comments import COMMENT_MAP VERSION="2.0" PROGRAM = sys.argv[0] -ROOT = os.path.abspath(os.getcwd()) -USER = os.getenv('USER') -VERBOSE = False -GERRORS = 0 -TMPDIR = '/dev/shm/alsatool' -REPOSITORIES = [ - 'alsa', 'alsa-driver', 'alsa-kmirror', 'alsa-lib', 'alsa-utils', - 'alsa-tools', 'alsa-firmware', 'alsa-oss', 'alsa-plugins', - 'alsa-python' -] -ALSA_FILES = ( - 'Documentation/sound/alsa/', - 'sound/', - 'include/sound/' -) -NOT_ALSA_FILES = ( - 'sound/oss/', -) - -def package(repo): - if repo == 'alsa-python': - return 'pyalsa' - return repo - -def tmpdir(extra=''): - if not os.path.exists(TMPDIR): - os.mkdir(TMPDIR) - if extra and extra[0] != '/': - extra = '/' + extra - if extra and not os.path.exists(TMPDIR + extra): - os.mkdir(TMPDIR + extra) - return os.path.abspath(TMPDIR + extra) - -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 + if repos is None or len(repos) == 0: + return config.REPOSITORIES[:] + else: + neg = repos[0][0] == '-' + if neg: + negres = config.REPOSITORIES + 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: + negres.remove(repo[1:]) + if neg: + repos = negres + for repo in repos: + if not repo in config.REPOSITORIES: + raise ValueError, "repository '%s' is unknown" % repo + return repos def xlist(argv=None): - s = '' - for i in REPOSITORIES: - s += i + ' ' - print(s[:-1]) + s = '' + for i in config.REPOSITORIES: + s += i + ' ' + print(s[:-1]) -def git(repo): - dir = ROOT + '/' + repo - return "git --work-tree=%s --git-dir=%s" % (dir, dir + '/.git') +def git(repo, dir=None): + if dir is None: + 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) + repos = selectrepos(argv) + for repo in repos: + print("clone", repo) def diff(argv=None): - repos = selectrepos(argv) - first = True - for repo in repos: - if not first: - print - first = False - print("%s" % repo) - print("*"*len(repo)) - pull([repo]) - if os.system("%s --no-pager diff origin/master..master" % git(repo)): - raise ValueError, "diff %s" % repo + repos = selectrepos(argv) + first = True + for repo in repos: + if not first: + print + first = False + print("%s" % repo) + print("*"*len(repo)) + pull([repo]) + if git_system(repo, "--no-pager diff origin/master..master"): + 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 origin master" % git(repo)): - raise ValueError, "pull %s" % repo + repos = selectrepos(argv) + for repo in repos: + if git_system(repo, "checkout master"): + raise ValueError, "checkout %s" % repo + os.chdir(ROOT + '/' + repo) + if git_system(repo, "%s pull origin master"): + 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 --tags origin master:refs/heads/master" % git(repo)): - raise ValueError, "push %s" % repo + repos = selectrepos(argv) + for repo in repos: + if git_system(repo, "checkout master"): + raise ValueError, "checkout %s" % repo + if git_system(repo, "push --tags origin master:refs/heads/master"): + 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:] - if c2 == '': - c2 = 'zzzzz' - 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 + 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:] + if c2 == '': + c2 = 'zzzzz' + 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, tag=None): - res = {} - if tag == "last": - tag = None - for repo in repos: - if repo == 'alsa': - continue - res[repo] = [] - mytag = tag - if not mytag: - tags = version_sort(os.popen("%s tag" % git(repo)).readlines()) - if not tags: - raise ValueError, "cannot obtain tags for repo %s" % repo - mytag = tags[-1] - fp = os.popen("%s diff --stat %s..HEAD" % (git(repo), mytag)) - 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 + res = {} + if tag == "last": + tag = None + for repo in repos: + if repo == 'alsa': + continue + res[repo] = [] + mytag = tag + if not mytag: + tags = version_sort(os.popen("%s tag" % git(repo)).readlines()) + if not tags: + raise ValueError, "cannot obtain tags for repo %s" % repo + mytag = tags[-1] + fp = os.popen("%s diff --stat %s..HEAD" % (git(repo), mytag)) + 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, tag) - for repo in res: - print('Repository %s has %s changed files' % (repo, len(res[repo]))) - if VERBOSE: - print(' ', line.strip()) + if argv == None: + tag = "last" + repos = selectrepos(None) + else: + tag = argv[0] + repos = selectrepos(argv[1:]) + res = showchanges1(repos, tag) + 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']) - files = [] - 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.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" - files.append('configure.in') - os.chdir(ROOT + '/alsa-kmirror') - #if os.system("git add include/version.h"): - # raise ValueError, "git add" - #if os.system('git commit -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): - # raise ValueError, "git add" - if os.system('git tag %s -a -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % (tag, tag)): - raise ValueError, "git tag" - 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)) - files.append('configure.in') - 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)) - files.append('Makefile') - 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)) - files.append('setup.py') - 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)) - files.append('PKG-INFO') - os.chdir(ROOT + '/' + repo) - for file in files: - if os.system("git add %s" % file): - raise ValueError, "git add %s" % file - if os.system('git commit -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): - raise ValueError, "git commit" - if os.system('git tag %s -a -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % (tag, tag)): - raise ValueError, "git tag" + print('') + print('Repository %s' % repo) + print(''.rjust(11 + len(repo), '*')) + version = tag[1:] + pull([repo]) + if repo == 'alsa-driver': + pull(['alsa-kmirror']) + files = [] + 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.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" + files.append('configure.in') + os.chdir(ROOT + '/alsa-kmirror') + #if os.system("git add include/version.h"): + # raise ValueError, "git add" + #if os.system('git commit -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): + # raise ValueError, "git add" + if os.system('git tag %s -a -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % (tag, tag)): + raise ValueError, "git tag" + 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)) + files.append('configure.in') + 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)) + files.append('Makefile') + 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)) + files.append('setup.py') + 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)) + files.append('PKG-INFO') + os.chdir(ROOT + '/' + repo) + for file in files: + if os.system("git add %s" % file): + raise ValueError, "git add %s" % file + if os.system('git commit -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): + raise ValueError, "git commit" + if os.system('git tag %s -a -m "Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % (tag, tag)): + raise ValueError, "git tag" 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') - if 'alsa-driver' in repos: - print('Updating alsa-kernel.git/include/sound/version.h...') - os.chdir(ROOT + '/' + 'alsa-kernel') - if os.system('git checkout master'): - raise ValueError, "git checkout master" - if os.system('git pull origin master'): - raise ValueError, "git pull origin master" - version = open('include/sound/version.h').read(4096) - pos1 = version.find("CONFIG_SND_VERSION") - pos2 = version[pos1:].find('"') - pos3 = version[pos1+pos2+1:].find('"') - active = version[pos1+pos2+1:pos1+pos2+pos3+1] - if active != tag[1:]: - version = version[:pos1+pos2] + '"' + tag[1:] + '"' + version[pos1+pos2+pos3+2:] - open('include/sound/version.h', 'w+').write(version) - if os.system('git add include/sound/version.h'): - raise ValueError, "git add" - if os.system('git commit -m "ALSA: Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): - raise ValueError, "git commit" - if os.system('git push origin master:refs/heads/master'): - raise ValueError, "git push" - else: - print('Already updated...') - print('Doing release for: %s' % ','.join(repos)) - for repo in repos: - release1(repo, tag) + 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') + if 'alsa-driver' in repos: + print('Updating alsa-kernel.git/include/sound/version.h...') + os.chdir(ROOT + '/' + 'alsa-kernel') + if os.system('git checkout master'): + raise ValueError, "git checkout master" + if os.system('git pull origin master'): + raise ValueError, "git pull origin master" + version = open('include/sound/version.h').read(4096) + pos1 = version.find("CONFIG_SND_VERSION") + pos2 = version[pos1:].find('"') + pos3 = version[pos1+pos2+1:].find('"') + active = version[pos1+pos2+1:pos1+pos2+pos3+1] + if active != tag[1:]: + version = version[:pos1+pos2] + '"' + tag[1:] + '"' + version[pos1+pos2+pos3+2:] + open('include/sound/version.h', 'w+').write(version) + if os.system('git add include/sound/version.h'): + raise ValueError, "git add" + if os.system('git commit -m "ALSA: Release %s\n\nSigned-off-by: Jaroslav Kysela \n"' % tag): + raise ValueError, "git commit" + if os.system('git push origin master:refs/heads/master'): + raise ValueError, "git push" + else: + print('Already updated...') + print('Doing release for: %s' % ','.join(repos)) + for repo in repos: + release1(repo, tag) def _merge_members(members, module='alsa-driver', nice=False): - def mgo(file, module): - global COMMENT_MAP - map = COMMENT_MAP[module] - if module == 'alsa-driver' and file[:6] == '/acore': - file = '/' + file[2:] - for i in map: - if re.compile("^" + i[0]).search(file): - if i[1] == 'ERROR': - break - return i[1] - if file.endswith('/.cvsignore'): - return 'IGNORE' - if file.endswith('/.hgignore'): - return 'IGNORE' - if file.endswith('/.gitignore'): - return 'IGNORE' - if file.endswith('/.hgtags'): - return 'IGNORE' - if file.endswith('/Makefile.am'): - return file - if file.endswith('/Makefile'): - return file - return 'ERROR' - - global GERRORS - - changes = [] - result = [] - for file in members: - file = "/" + file - while file != '': - result1 = mgo(file, module) - if result1 == 'ERROR': - GERRORS += 1 - str = 'Cannot identify file "%s" from module %s' % (file, module) - fp = open("/tmp/changes-log.txt", "a+") - fp.write(str + "\n") - fp.close() - print(str, ' {see /tmp/changes-log.txt file}') - result1 = '' - if result1 != '': - file = '' - changes.append(result1) - else: - i = file.rfind('/') - if i < 0: - file = '' - else: - file = file[0:i] - i = 0 - while i < len(changes): - j = 0 - while j < len(changes): - if i != j and changes[i] == changes[j]: - del changes[j] - i = -1 - break - j += 1 - i += 1 - xresult = '' - maxc = 70 - if nice: - maxc = 61 - for i in changes: - if len(i) + len(xresult) > maxc: - result.append(xresult) - xresult = '' - if xresult == '': - xresult = i - else: - xresult = xresult + ',' + i - if xresult != '': - result.append(xresult) - if len(result) > 1 and nice: - return [] - elif len(result) > 0 and nice: - result[0] = "Modules: " + result[0] - result.append('') - return result - -def parse_log(fp): - commits = [] - commitref = '' - commit = {'comment':[], 'files':[]} - header = True - while 1: - line = fp.readline() - if not line: - break - if line.startswith('commit '): - if commitref: - while commit['comment'][-1] == '\n': - del commit['comment'][-1] - commits.append(commit) - commitref = line[7:].strip() - commit = {'comment':[], 'files':[]} - commit['commit'] = commitref - elif line.startswith('Author:') or line.startswith('AuthorDate:') or \ - line.startswith('Commit:') or line.startswith('CommitDate:') or \ - line.startswith('Merge:'): - a = line.split(': ') - commit[a[0].strip()] = (': '.join(a[1:])).strip() - elif line.startswith(' '): - if len(commit['comment']) == 0 and line[4:].strip() == '': - continue - commit['comment'].append(line[4:]) - elif line.strip() != '': - commit['files'].append(line.strip()) - if commitref: - while commit['comment'][-1] == '\n': - del commit['comment'][-1] - commits.append(commit) - return commits + def mgo(file, module): + global COMMENT_MAP + map = COMMENT_MAP[module] + if module == 'alsa-driver' and file[:6] == '/acore': + file = '/' + file[2:] + for i in map: + if re.compile("^" + i[0]).search(file): + if i[1] == 'ERROR': + break + return i[1] + if file.endswith('/.cvsignore'): + return 'IGNORE' + if file.endswith('/.hgignore'): + return 'IGNORE' + if file.endswith('/.gitignore'): + return 'IGNORE' + if file.endswith('/.hgtags'): + return 'IGNORE' + if file.endswith('/Makefile.am'): + return file + if file.endswith('/Makefile'): + return file + return 'ERROR' + + global GERRORS + + changes = [] + result = [] + for file in members: + file = "/" + file + while file != '': + result1 = mgo(file, module) + if result1 == 'ERROR': + GERRORS += 1 + str = 'Cannot identify file "%s" from module %s' % (file, module) + fp = open("/tmp/changes-log.txt", "a+") + fp.write(str + "\n") + fp.close() + print(str, ' {see /tmp/changes-log.txt file}') + result1 = '' + if result1 != '': + file = '' + changes.append(result1) + else: + i = file.rfind('/') + if i < 0: + file = '' + else: + file = file[0:i] + i = 0 + while i < len(changes): + j = 0 + while j < len(changes): + if i != j and changes[i] == changes[j]: + del changes[j] + i = -1 + break + j += 1 + i += 1 + xresult = '' + maxc = 70 + if nice: + maxc = 61 + for i in changes: + if len(i) + len(xresult) > maxc: + result.append(xresult) + xresult = '' + if xresult == '': + xresult = i + else: + xresult = xresult + ',' + i + if xresult != '': + result.append(xresult) + if len(result) > 1 and nice: + return [] + elif len(result) > 0 and nice: + result[0] = "Modules: " + result[0] + result.append('') + return result 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-kmirror': - module = 'alsa-driver' - for a in logs: - 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 = _merge_members(change['files'], module) - if len(members) == 0: - continue - members = members[0] - mems = members.split(',') - 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 item.find('Core') >= 0: - items[core].append(item) - if item.find('Midlevel') >= 0: - items[midlevel].append(item) - if item.find('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.strip() - if len(a) != len(rev): - continue - if a == rev: - return True - return False - - def esc(str): - return str.replace('>', '>').replace('<', '<').replace('&', '&') - - try: - rev1 = argv[0] - rev2 = argv[1] - except: - sys.stderr.write('Please, specify oldtag and newtag\n') - sys.exit(1) - - changes = [] - fullset = REPOSITORIES - fromrev = {} - - p = re.compile('.*[a-z]+') - rev2last = rev2 - if not p.match(rev2[1:]): - rev2last = rev2 + 'zzzzz' - - for module in fullset: - xrev = rev1 - fp = os.popen("%s tag 2> /dev/null" % 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.strip()[:-1] - if a >= rev2last: - continue - if tag.strip() != rev2: - tags1.append(tag) - 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 - fp = os.popen("%s log --pretty=fuller --date=iso --name-only --reverse %s..%s" % (git(module), xrev, rev2)) - commits = parse_log(fp) - del fp - store_changes(changes, commits, 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('') - print('') - print('Changes %s %s' % (rev1, rev2)) - print('') - print('1') - print('Perex2') - print('') - 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===' % esc(b)) - for a in res[module][b]: - log = a['comment'][0] - if log[:9] == 'Summary: ': - log = log[9:] - elif log[:8] == 'Summary:': - log = log[8:] - print(': %s' % esc(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===' % esc(b)) - for a in res[module][b]: - log = a['comment'] - first = "-" - for l in log: - if l[:13] == "Patch-level: ": - continue - if l[:13] == "Patch-Level: ": - continue - print(': %s %s' % (first, esc(l[:-1]))) - first = " " - print('') - print('') - print('') - print('') + 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-kmirror': + module = 'alsa-driver' + for a in logs: + 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 = _merge_members(change['files'], module) + if len(members) == 0: + continue + members = members[0] + mems = members.split(',') + 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 item.find('Core') >= 0: + items[core].append(item) + if item.find('Midlevel') >= 0: + items[midlevel].append(item) + if item.find('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.strip() + if len(a) != len(rev): + continue + if a == rev: + return True + return False + + def esc(str): + return str.replace('>', '>').replace('<', '<').replace('&', '&') + + try: + rev1 = argv[0] + rev2 = argv[1] + except: + sys.stderr.write('Please, specify oldtag and newtag\n') + sys.exit(1) + + changes = [] + fullset = REPOSITORIES + fromrev = {} + + p = re.compile('.*[a-z]+') + rev2last = rev2 + if not p.match(rev2[1:]): + rev2last = rev2 + 'zzzzz' + + for module in fullset: + xrev = rev1 + fp = os.popen("%s tag 2> /dev/null" % 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.strip()[:-1] + if a >= rev2last: + continue + if tag.strip() != rev2: + tags1.append(tag) + 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 + commits = git_read_commits(module, xrev, rev2) + store_changes(changes, commits, 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('') + print('') + print('Changes %s %s' % (rev1, rev2)) + print('') + print('1') + print('Perex2') + print('') + 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===' % esc(b)) + for a in res[module][b]: + log = a['comment'].splitlines()[0] + if log[:9] == 'Summary: ': + log = log[9:] + elif log[:8] == 'Summary:': + log = log[8:] + print(': %s' % esc(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===' % esc(b)) + for a in res[module][b]: + log = a['comment'].splitlines() + first = "-" + for l in log: + if l[:13] == "Patch-level: ": + continue + if l[:13] == "Patch-Level: ": + continue + print(': %s %s' % (first, esc(l[:-1]))) + first = " " + print('') + print('') + print('') + print('') 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].replace('\n', '\t\t')) + 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].replace('\n', '\t\t')) + print('') + print('Where command is:') + for cmd in CMDS: + print('') + print("\t%s %s" % (cmd[0], cmd[2])) + print("\t\t%s" % cmd[3].replace('\n', '\n\t\t')) + if msg: print('') - print('Where command is:') - for cmd in CMDS: - print('') - print("\t%s %s" % (cmd[0], cmd[2])) - print("\t\t%s" % cmd[3].replace('\n', '\n\t\t')) - if msg: - print('') - print(msg) - sys.exit(code) + 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]) + if argv == None: + eprint('Specify root directory.') + sys.exit(1) + config.ROOT=os.path.abspath(argv[0]) def verbose(argv): - global VERBOSE - VERBOSE=True + global VERBOSE + VERBOSE=True def extpick(argv, edit=False, sign=False, interactive=True): - if argv[0] in ['-s', '--signoff']: - sign = True - del argv[0] - sign = sign and ' --signoff' or ' --committer' - interactive = interactive and ' -i' or '' - repo = os.path.abspath(argv[0]) - commit = argv[1] - tmpdir = ".extpick" - if not os.path.exists(tmpdir): - os.mkdir(tmpdir) - if os.system("git --work-tree=%s --git-dir=%s format-patch -k --stdout --full-index --committer %s~1..%s > %s" % (repo, repo + '/.git', commit, commit, tmpdir + '/format-patch')): - raise ValueError, "format-patch" - lines = open(tmpdir + "/format-patch").readlines() - for idx in range(0, len(lines)): - if lines[idx].startswith('Subject: '): - a = lines[idx][8:].strip() - if not a.upper().startswith('[ALSA]') and \ - not a.upper().startswith('ALSA:') and \ - not a.upper().startswith('[SOUND]') and \ - not a.upper().startswith('SOUND:'): - if a.upper().startswith('SOUNDS: '): - a = a[8:].strip() - lines[idx] = 'Subject: sound: ' + a + '\n' - break - open(tmpdir + "/format-patch", "w+").write(''.join(lines)) - if edit: - editor = os.environ.has_key('EDITOR') and os.environ['EDITOR'] or 'vi' - copyfile(tmpdir + "/format-patch", tmpdir + "/format-patch.orig") - os.system("%s %s" % (editor, tmpdir + "/format-patch")) - if not os.system("diff %s %s > /dev/null" % (tmpdir + "/format-patch", tmpdir + "/format-patch.orig")): - return "nochanges" - res = os.system("git am%s%s -3 --keep %s" % (sign, interactive, tmpdir + '/format-patch')) - #if os.system("git --work-tree=%s --git-dir=%s mailinfo -u %s %s < %s > %s" % (repo, repo + '/.git', tmpdir + '/msg', tmpdir + '/patch', tmpdir + '/format-patch', tmpdir + '/info')): - # raise ValueError, "mail-info" - rmtree(tmpdir) - return res - -def kmirrorpick(argv, edit=True, sign=False, interactive=True): - if argv[0] in ['-s', '--signoff']: - sign = True - del argv[0] - sign = sign and ' --signoff' or ' --committer' - interactive = interactive and ' -i' or '' - repo = os.path.abspath(argv[0]) - commit = argv[1] - tmpdir = ".kmirrorpick" - if not os.path.exists(tmpdir): - os.mkdir(tmpdir) - if os.system("git --work-tree=%s --git-dir=%s format-patch -k --stdout --full-index --committer %s~1..%s > %s" % (repo, repo + '/.git', commit, commit, tmpdir + '/format-patch')): - raise ValueError, "format-patch" - #lines = open(tmpdir + "/format-patch").readlines() - #open(tmpdir + "/format-patch", "w+").write(''.join(newlines)) - if edit: - editor = os.environ.has_key('EDITOR') and os.environ['EDITOR'] or 'vi' - copyfile(tmpdir + "/format-patch", tmpdir + "/format-patch.orig") - os.system("%s %s" % (editor, tmpdir + "/format-patch")) - if not os.system("diff %s %s > /dev/null" % (tmpdir + "/format-patch", tmpdir + "/format-patch.orig")): - return "nochanges" - res = os.system("git am%s%s -3 --keep %s" % (sign, interactive, tmpdir + '/format-patch')) - if res == 256: - res = os.system("LANG=C patch -p2 < %s > %s" % (tmpdir + '/format-patch', tmpdir + '/patch.out')) - lines = open(tmpdir + '/patch.out').readlines() - sys.stdout.write(''.join(lines)) - if res == 0: - for line in lines: - if line.startswith('patching file '): - os.system("git add %s" % line[13:]) - os.system("git am -3 --resolved") - #if os.system("git --work-tree=%s --git-dir=%s mailinfo -u %s %s < %s > %s" % (repo, repo + '/.git', tmpdir + '/msg', tmpdir + '/patch', tmpdir + '/format-patch', tmpdir + '/info')): - # raise ValueError, "mail-info" - #rmtree(tmpdir) - return res + if argv[0] in ['-s', '--signoff']: + sign = True + del argv[0] + sign = sign and ' --signoff' or '' + interactive = interactive and ' -i' or '' + repo = os.path.abspath(argv[0]) + commit = argv[1] + tmpdir = ".extpick" + if not os.path.exists(tmpdir): + os.mkdir(tmpdir) + if git_system('.', "format-patch -k --stdout --full-index %s~1..%s > %s" % (commit, commit, tmpdir + '/format-patch')): + raise ValueError, "format-patch" + lines = open(tmpdir + "/format-patch").readlines() + for idx in range(0, len(lines)): + if lines[idx].startswith('Subject: '): + a = lines[idx][8:].strip() + if not a.upper().startswith('[ALSA]') and \ + not a.upper().startswith('ALSA:') and \ + not a.upper().startswith('[SOUND]') and \ + not a.upper().startswith('SOUND:') and \ + not a.upper().startswith('ASOC:'): + if a.upper().startswith('SOUNDS: '): + a = a[8:].strip() + lines[idx] = 'Subject: sound: ' + a + '\n' + break + open(tmpdir + "/format-patch", "w+").write(''.join(lines)) + if edit: + editor = os.environ.has_key('EDITOR') and os.environ['EDITOR'] or 'vi' + copyfile(tmpdir + "/format-patch", tmpdir + "/format-patch.orig") + os.system("%s %s" % (editor, tmpdir + "/format-patch")) + if not os.system("diff %s %s > /dev/null" % (tmpdir + "/format-patch", tmpdir + "/format-patch.orig")): + rmtree(tmpdir) + return "nochanges" + res = os.system("git am%s%s -3 --keep %s" % (sign, interactive, tmpdir + '/format-patch')) + #if os.system("git --work-tree=%s --git-dir=%s mailinfo -u %s %s < %s > %s" % (repo, repo + '/.git', tmpdir + '/msg', tmpdir + '/patch', tmpdir + '/format-patch', tmpdir + '/info')): + # raise ValueError, "mail-info" + rmtree(tmpdir) + return res + +def kmirrorpick(argv, edit=False, sign=False, interactive=True): + while argv: + if argv[0] in ['-s', '--signoff']: + sign = True + del argv[0] + elif argv[0] in ['-e', '--edit']: + edit = True + else: + break + sign = sign and ' --signoff' or '' + interactive = interactive and ' -i' or '' + repo = git_repo(argv[0]) + commit = argv[1] + tmpdir = ".kmirrorpick" + if not os.path.exists(tmpdir): + os.mkdir(tmpdir) + if os.system("git --work-tree=%s --git-dir=%s format-patch -k --stdout --full-index %s~1..%s > %s" % (repo, repo + '/.git', commit, commit, tmpdir + '/format-patch')): + raise ValueError, "format-patch" + lines, addfiles, rmfiles = analyze_diff(open(tmpdir + "/format-patch"), full=True) + open(tmpdir + "/format-patch", "w+").write(''.join(lines)) + if edit: + editor = os.environ.has_key('EDITOR') and os.environ['EDITOR'] or 'vi' + copyfile(tmpdir + "/format-patch", tmpdir + "/format-patch.orig") + os.system("%s %s" % (editor, tmpdir + "/format-patch")) + if not os.system("diff %s %s > /dev/null" % (tmpdir + "/format-patch", tmpdir + "/format-patch.orig")): + return "nochanges" + res = os.system("git am%s%s -3 --keep %s" % (sign, interactive, tmpdir + '/format-patch')) + if res == 256: + res = os.system("LANG=C patch -p2 < %s > %s" % (tmpdir + '/format-patch', tmpdir + '/patch.out')) + lines = open(tmpdir + '/patch.out').readlines() + sys.stdout.write(''.join(lines)) + if res == 0: + for line in lines: + if line.startswith('patching file '): + os.system("git add %s" % line[13:]) + os.system("git am -3 --resolved") + #if os.system("git --work-tree=%s --git-dir=%s mailinfo -u %s %s < %s > %s" % (repo, repo + '/.git', tmpdir + '/msg', tmpdir + '/patch', tmpdir + '/format-patch', tmpdir + '/info')): + # raise ValueError, "mail-info" + #rmtree(tmpdir) + return res def edit(argv, remove=False): - commit = argv[0] - fp = os.popen("git log --pretty=oneline --reverse %s~1..HEAD" % commit) - commits = [] - tmpdir = ".editmsg" - if not os.path.exists(tmpdir): - os.mkdir(tmpdir) - while 1: - line = fp.readline() - if not line: - break - commits.append(line.split(' ')[0]) - open(tmpdir + '/commits', "w+").write('\n'.join(commits)) - head = os.popen("git rev-parse HEAD").readline().strip() - print("Original HEAD is %s..." % head) - print("Removed commits are in %s..." % tmpdir + '/commits') - print("Resetting tree to %s..." % os.popen("git log --pretty=oneline %s~1..%s" % (commit, commit)).readline().strip()) - if os.system("git reset --hard %s~1" % commit): - raise ValueError, "git reset" - first = True - for commit in commits: - if remove and first: - first = False - continue - res = extpick(['.', commit], edit=first, interactive=True) - if type(res) == type('') and res == "nochanges": - print("No changes, resetting back to %s..." % head) - sys.exit(os.system("git reset --hard %s" % head)) - if res: - sys.stderr.write("Error, bailing out\n") - sys.exit(1) - first = False - rmtree(tmpdir) + commit = argv[0] + fp = os.popen("git log --pretty=oneline --reverse %s~1..HEAD" % commit) + commits = [] + tmpdir = ".editmsg" + if not os.path.exists(tmpdir): + os.mkdir(tmpdir) + while 1: + line = fp.readline() + if not line: + break + commits.append(line.split(' ')[0]) + open(tmpdir + '/commits', "w+").write('\n'.join(commits)) + head = os.popen("git rev-parse HEAD").readline().strip() + print("Original HEAD is %s..." % head) + print("Removed commits are in %s..." % tmpdir + '/commits') + print("Resetting tree to %s..." % os.popen("git log --pretty=oneline %s~1..%s" % (commit, commit)).readline().strip()) + if os.system("git reset --hard %s~1" % commit): + raise ValueError, "git reset" + first = True + for commit in commits: + if remove and first: + first = False + continue + res = extpick(['.', commit], edit=first, interactive=True) + if type(res) == type('') and res == "nochanges": + print("No changes, resetting back to %s..." % head) + sys.exit(os.system("git reset --hard %s" % head)) + if res: + sys.stderr.write("Error, bailing out\n") + sys.exit(1) + first = False + rmtree(tmpdir) def remove(argv): - edit(argv, remove=True) + edit(argv, remove=True) def import_(argv): - from sha import new as sha_new - - def compare(commit1, commit2): - diff1 = os.popen("git diff %s~1..%s" % (commit1, commit1)).readlines() - diff2 = os.popen("git diff %s~1..%s" % (commit2, commit2)).readlines() - if len(diff1) != len(diff2): - return False - for idx in range(0, len(diff1)-1): - if diff1[idx].startswith('index ') and diff2[idx].startswith('index '): - continue - elif diff1[idx].startswith('@@ ') and diff2[idx].startswith('@@ '): - a = diff1[idx].split(' ') - b = diff2[idx].split(' ') - a1 = a[1].split(',') - a2 = a[2].split(',') - b1 = b[1].split(',') - b2 = b[2].split(',') - if len(a1) < 2: - a1.append('XXX') - if len(b1) < 2: - b1.append('XXX') - if a1[1] != b1[1] or a2[1] != b2[1]: - return False - elif diff1[idx] != diff2[idx]: - return False - return True - - def is_blacklisted(commit): - hexdigest = sha_new(os.popen("git diff %s~1..%s" % (commit, commit)).read(10*1024*1024)).hexdigest() - return hexdigest in blacklist - - def do_blacklist(commit): - diff1 = os.popen("git diff %s~1..%s" % (commit['commit'], commit['commit'])).read(10*1024*1024) - digest = sha_new(diff1).hexdigest() - if not digest in blacklist: - subject = commit['comment'][0].strip() - open(".git/import-blacklist", "a+").write(digest + ' ' + subject + '\n') - else: - print('Already blacklisted...') - - if os.path.exists('.dotest'): - sys.stderr.write('previous dotest directory .dotest still exists\n') - return 1 - blacklist1 = open(".git/import-blacklist").readlines() - blacklist = [] - for l in blacklist1: - blacklist.append(l[:l.find(' ')]) - del blacklist1 - branch = argv[0] - base = os.popen("git merge-base master %s" % branch).readline().strip() - log1 = parse_log(os.popen("git log --pretty=fuller --date=iso --reverse master..%s" % branch)) - log2 = parse_log(os.popen("git log --pretty=fuller --date=iso --reverse %s..master" % base)) - tomerge = [] - skipcount = 0 - for l1 in log1: - if l1.has_key('Merge'): - continue - subject1 = l1['comment'][0].strip() - merged = False - blacklisted = False - for l2 in log2: - subject2 = l2['comment'][0].strip() - if subject1 == subject2: - if compare(l1['commit'], l2['commit']): - merged = True - break - if not merged and is_blacklisted(l1['commit']): - merged = True - blacklisted = True - if merged: - skipcount += 1 - print("Already picked%s:" % (blacklisted and '/blacklisted' or '')) - print("** %s/%s %s" % (branch, l1['commit'][:7], l1['comment'][0][:-1])) - if not blacklisted: - print("** master/%s %s" % (l2['commit'][:7], l2['comment'][0][:-1])) - else: - tomerge.append(l1) - print('Already merged patches: %s' % skipcount) - print('Patches to be merged: %s' % len(tomerge)) - for l1 in tomerge: - oldrev = os.popen("git rev-parse HEAD").readline().strip() - if extpick(['.', l1['commit']], sign=True): - sys.stderr.write('An error occured...\n') - return 1 - rev = os.popen("git rev-parse HEAD").readline().strip() - if oldrev == rev: - sys.stdout.write('No change, do you want to black list this patch? (Y/ ) ') - sys.stdout.flush() - line = sys.stdin.readline() - if line.startswith('Y'): - do_blacklist(l1) - return 0 - -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 read_git_ok_commits(): - git_ok_commits = [] - fp = open(ROOT + '/alsa/kernel-sync/git-ok-commits') - while 1: - line = fp.readline() - if not line: - break - if line.startswith('#'): - continue - git_ok_commits.append(line.strip()) - fp.close() - del fp - return git_ok_commits - -def mark_git_ok_commits(git_ok_commits, commit): - line = '"' + commit['Author'] + '" "' + commit['AuthorDate'] + \ - '" "' + commit['Commit'] + '" "' + commit['CommitDate'] + '"' - if line in git_ok_commits: - print("Commit already marked: %s %s" % (commit['commit'][:7], commit['comment'][0].strip())) - return False - git_ok_commits.append(line) - fp = open(ROOT + '/alsa/kernel-sync/git-ok-commits', 'a+') - fp.write(line + '\n') - fp.close() - del fp - print("Commit added: %s %s" % (commit['commit'][:7], commit['comment'][0].strip())) - return True + from hashlib import sha1 as sha_new + + def is_blacklisted(commit): + hexdigest = sha_new(os.popen("git diff %s~1..%s" % (commit, commit)).read(10*1024*1024)).hexdigest() + return hexdigest in blacklist + + def do_blacklist(commit): + diff1 = os.popen("git diff %s~1..%s" % (commit['ref'], commit['ref'])).read(10*1024*1024) + digest = sha_new(diff1).hexdigest() + if not digest in blacklist: + subject = commit['comment'].splitlines()[0].strip() + open(".git/import-blacklist", "a+").write(digest + ' ' + subject + '\n') + else: + print('Already blacklisted...') + + if os.path.exists('.dotest'): + sys.stderr.write('previous dotest directory .dotest still exists\n') + return 1 + blacklist1 = open(".git/import-blacklist").readlines() + blacklist = [] + for l in blacklist1: + blacklist.append(l[:l.find(' ')]) + del blacklist1 + branch = argv[0] + base = os.popen("git merge-base master %s" % branch).readline().strip() + log1 = git_read_commits('.', 'master', branch, reverse=True) + log2 = git_read_commits('.', base, 'master', reverse=True) + tomerge = [] + skipcount = 0 + for l1 in log1: + if l1.has_key('Merge'): + continue + subject1 = raw_subject(l1['comment'].splitlines()[0]) + merged = False + blacklisted = False + for l2 in log2: + subject2 = raw_subject(l2['comment'].splitlines()[0]) + if subject1 == subject2: + merged = True + break + if not merged and is_blacklisted(l1['ref']): + merged = True + blacklisted = True + if merged: + skipcount += 1 + print("Already picked%s:" % (blacklisted and '/blacklisted' or '')) + print("** %s/%s %s" % (branch, l1['ref'][:7], l1['comment'].splitlines()[0][:-1])) + if not blacklisted: + print("** master/%s %s" % (l2['ref'][:7], l2['comment'].splitlines()[0][:-1])) + else: + tomerge.append(l1) + print('Already merged patches: %s' % skipcount) + print('Patches to be merged: %s' % len(tomerge)) + for l1 in tomerge: + oldrev = os.popen("git rev-parse HEAD").readline().strip() + if extpick(['.', l1['ref']], sign=True, interactive=False): + if os.system("git am -3 --abort") or \ + os.system("git reset --hard"): + raise ValueError + sys.stderr.write('An error occured... Skipping...\n') + rev = os.popen("git rev-parse HEAD").readline().strip() + if oldrev == rev: + sys.stdout.write('No change, do you want to black list this patch? (Y/ ) ') + sys.stdout.flush() + line = sys.stdin.readline() + if line.startswith('Y'): + do_blacklist(l1) + return 0 def getorigin(repo = 'alsa-kernel'): - from httplib import HTTP - h = HTTP('git.alsa-project.org') - h.putrequest('GET', 'http://git.alsa-project.org/http/%s.git/refs/heads/master' % repo) - h.endheaders() - h.getreply() - origin = h.getfile().read(1024) - h.close() - origin = origin.strip() - if len(origin) != 40: - raise ValueError, "git.alsa-project.org is down?" - return origin - -def kmirrorcheck(argv): - - def compare(commit1, commit2): - diff1 = os.popen("git diff %s~1..%s" % (commit1, commit1)).readlines() - os.chdir(ROOT + '/alsa-kmirror') - diff2 = os.popen("git diff %s~1..%s" % (commit2, commit2)).readlines() - os.chdir(ROOT + '/alsa-kernel') - if len(diff1) != len(diff2): - return False - for idx in range(0, len(diff1)-1): - if diff1[idx].startswith('index ') and diff2[idx].startswith('index '): - continue - elif diff1[idx].startswith('diff --git') and diff2[idx].startswith('diff --git'): - continue - elif diff1[idx].startswith('--- a/') and diff2[idx].startswith('--- a/'): - continue - elif diff1[idx].startswith('+++ b/') and diff2[idx].startswith('+++ b/'): - continue - elif diff1[idx].startswith('@@ ') and diff2[idx].startswith('@@ '): - a = diff1[idx].split(' ') - b = diff2[idx].split(' ') - a1 = a[1].split(',') - a2 = a[2].split(',') - b1 = b[1].split(',') - b2 = b[2].split(',') - if a1[1] != b1[1] or a2[1] != b2[1]: - return False - elif diff1[idx] != diff2[idx]: - print(repr(diff1[idx]), repr(diff2[idx])) - return False - return True - - def mystrip(str): - if str.startswith('ALSA:') or str.startswith('alsa:'): - str = str[5:] - elif str.startswith('SOUND:') or str.startswith('sound:'): - str = str[6:] - elif str.startswith('[ALSA]'): - str = str[6:] - return str.strip() - - full = argv and argv[0] == 'full' - fromrev = 'linux-2.6' - if argv and len(argv) > 1: - fromrev = argv[1] - - print("Analyzing git-ok-commits..") - git_ok_commits = read_git_ok_commits() - - print("Analyzing alsa-kmirror..") - os.chdir(ROOT + '/alsa-kmirror') - if os.system("git checkout master"): - raise ValueError, "kmirror: git checkout master" - if os.system("git pull origin master"): - raise ValueError, "kmirror: git pull origin master" - kcommits = parse_log(os.popen("git log --reverse --pretty=fuller --date=iso v1.0.19..HEAD")) - print("Found %s commits after v1.0.19" % len(kcommits)) - - os.chdir(ROOT + '/alsa-kernel') - if full: - log1 = os.popen("git log --reverse --name-only --pretty=oneline --date=iso %s..master" % fromrev) - else: - print("Looking for a common base...") - base = os.popen("git merge-base %s linux-2.6" % getorigin()).read(1024).strip() - if not base: - raise ValueError, "base" - print("Base is %s" % repr(base)) - log1 = os.popen("git log --reverse --name-only --pretty=oneline --date=iso %s..linux-2.6" % base) - last = '' - ok = False - commits = [] - while 1: - line = log1.readline() - if not line: - break - if line[:40].find('/') > 0: - if is_alsa_file(line[:-1]): - ok = True - else: - if last and ok: - commits.append(last[:40]) - last = line - ok = False - if last and ok: - commits.append(last[:40]) - log1.close() - - print("Found %s commits to be checked..." % len(commits)) - changes = 0 - msg = [] - for commit in commits: - fuller = parse_log(os.popen("git log --name-only --pretty=fuller --date=iso %s~1..%s" % (commit, commit)))[0] - if fuller.has_key('Merge'): - continue - for l2 in kcommits: - subj1 = mystrip(fuller['comment'][0]) - subj2 = mystrip(l2['comment'][0]) - if subj1 == subj2: - if compare(fuller['commit'], l2['commit']): - if mark_git_ok_commits(git_ok_commits, fuller): - msg.append(' %s %s\n' % (fuller['commit'][:7], fuller['comment'][0].strip())) - changes += 1 - else: - print('Subject Match:') - print(' %s %s' % (fuller['commit'][:7], fuller['comment'][0].strip())) - print(' %s %s' % (l2['commit'][:7], l2['comment'][0].strip())) - print('') - print('%s commits were marked as duplicate..' % changes) - if changes: - msg.insert(0, 'git-ok-commits: added already merged patches\n\n') - msg.append('\nSigned-off-by: Jaroslav Kysela \n') - os.chdir(ROOT + '/alsa') - os.system("git add kernel-sync/git-ok-commits") - msg = ''.join(msg).replace('"', '\\"') - os.system("git commit -m \"%s\" -e" % ''.join(msg)) - -def kmirrormark(argv): - msg = [] - for commit in argv: - fuller = parse_log(os.popen("git log --name-only --pretty=fuller --date=iso %s~1..%s" % (commit, commit)))[0] - if fuller: - git_ok_commits = read_git_ok_commits() - if mark_git_ok_commits(git_ok_commits, fuller): - msg.append('git-ok-commits: added %s %s\n' % (fuller['commit'][:7], fuller['comment'][0].replace('"', "'").strip())) - else: - print 'Wrong commit ID: %s' % commit - if msg: - msg.append('\nSigned-off-by: Jaroslav Kysela \n') - os.chdir(ROOT + '/alsa') - os.system("git add kernel-sync/git-ok-commits") - os.system("git commit -m \"%s\" -e" % ''.join(msg)) - os.system("git push") + from httplib import HTTP + h = HTTP('git.alsa-project.org') + h.putrequest('GET', 'http://git.alsa-project.org/http/%s.git/refs/heads/master' % repo) + h.endheaders() + h.getreply() + origin = h.getfile().read(1024) + h.close() + origin = origin.strip() + if len(origin) != 40: + raise ValueError, "git.alsa-project.org is down?" + return origin def mailit(msg, subject): - from email.MIMEText import MIMEText - import smtplib - import time - - msg = MIMEText(msg, 'plain', 'utf-8') - msg['Subject'] = subject - msg['Message-Id'] = '' % time.time() - msg['From'] = 'alsatool@alsa-project.org' - msg['Reply-To'] = 'noreply@alsa-project.org' - msg['To'] = 'perex@perex.cz' - s = smtplib.SMTP() - s.connect() - s.sendmail(msg['From'], msg['To'], msg.as_string()) - s.close() - print("An email to %s was sent!" % msg['To']) + from email.MIMEText import MIMEText + import smtplib + import time + + msg = MIMEText(msg, 'plain', 'utf-8') + msg['Subject'] = subject + msg['Message-Id'] = '' % time.time() + msg['From'] = 'alsatool@alsa-project.org' + msg['Reply-To'] = 'noreply@alsa-project.org' + msg['To'] = 'perex@perex.cz' + s = smtplib.SMTP() + s.connect() + s.sendmail(msg['From'], msg['To'], msg.as_string()) + s.close() + print("An email to %s was sent!" % msg['To']) def tolinus(argv): - from datetime import datetime - branch = argv[0] - if not branch in ["for-linus"]: - raise ValueError, "branch %s" % branch - today = datetime.today() - patch = "alsa-git-%s-%04i-%02i-%02i.patch" % (branch, today.year, today.month, today.day) - lines = """ + from datetime import datetime + branch = argv[0] + if not branch in ["for-linus"]: + raise ValueError, "branch %s" % branch + today = datetime.today() + patch = "alsa-git-%s-%04i-%02i-%02i.patch" % (branch, today.year, today.month, today.day) + lines = """ Linus, please pull from: git pull git://git.alsa-project.org/alsa-kernel.git %s @@ -1114,181 +861,202 @@ Additional notes: The following files will be updated: """ % (branch, branch, patch) - lines1 = os.popen("git diff -M --stat --summary linux-2.6..%s" % branch).readlines() - for line in lines1: - if not line.startswith(' create mode'): - lines += line - lines += '\n' - lines += os.popen("git rev-list --no-merges --pretty=short linux-2.6..%s | git shortlog" % branch).read(10*1024*1024) - filename = tmpdir() + '/' + patch - if os.system("git diff -r linux-2.6..%s > %s" % (branch, filename)): - raise ValueError, "git diff" - if os.system("gzip -9 %s" % filename): - raise ValueError, "gzip" - if os.system("scp %s.gz root@alsa:/var/data/ftp/pub/kernel-patches" % filename): - raise ValueError, "scp" - os.remove(filename + '.gz') - mailit(msg=''.join(lines), subject='[ALSA PATCH] alsa-git merge request') - print(lines) + lines1 = os.popen("git diff -M --stat --summary linux-2.6..%s" % branch).readlines() + for line in lines1: + if not line.startswith(' create mode'): + lines += line + lines += '\n' + lines += os.popen("git rev-list --no-merges --pretty=short linux-2.6..%s | git shortlog" % branch).read(10*1024*1024) + filename = tmpdir() + '/' + patch + if os.system("git diff -r linux-2.6..%s > %s" % (branch, filename)): + raise ValueError, "git diff" + if os.system("gzip -9 %s" % filename): + raise ValueError, "gzip" + if os.system("scp %s.gz root@alsa:/var/data/ftp/pub/kernel-patches" % filename): + raise ValueError, "scp" + os.remove(filename + '.gz') + mailit(msg=''.join(lines), subject='[ALSA PATCH] alsa-git merge request') + print(lines) def kimport(argv=None): - repos = {} - if argv: - for i in argv: - a, b = i.split(i.find(':') > 0 and ':' or '/') - if not a or not b: - raise ValueError, "repo syntax error" - repos[a] = b - print 'Checking if a pull from the origin tree is required...' - rev = getorigin() - rev2 = os.popen("git merge-base %s master 2> /dev/null" % rev) - if not rev2 or rev2 == rev: - if os.system("git checkout master"): - raise ValueError, "git checkout master" - if os.system("git pull origin master"): - raise ValueError, "git pull origin master" - if not argv: - rev = os.popen("git rev-parse linux-2.6") - print('Pulling and rebasing to latest linux-2.6 tree') - if os.system("git checkout linux-2.6"): - raise ValueError, "git checkout linux-2.6" - if os.system("git pull --tags linux-2.6 master"): - raise ValueError, "git pull linux-2.6" - if os.system("git push --tags origin linux-2.6:refs/heads/linux-2.6"): - raise ValueError, "git push origin linux-2.6" - rev2 = os.popen("git rev-parse linux-2.6") - if rev != rev2 and os.system("git rebase --committer linux-2.6 master"): - raise ValueError, "git rebase" - for repo in repos: - print('Trying to import patches from %s/%s' % (repo, repos[repo])) - rev = os.popen("git rev-parse %s 2> /dev/null" % repo) - if rev: - if os.system("git checkout %s" % repo): - raise ValueError, "git checkout %s" % repo - if os.system("git pull %s %s" % (repo, repos[repo])): - print('Incremental pull from repo %s/%s failed.. Trying full operation...' % (repo, repos[repo])) - rev = '' - if not rev: - base = os.popen("git merge-base linux-2.6 %s 2> /dev/null" % repo) - print('Merge base %s' % base) - base = base and base or 'linux-2.6' - if os.system("git branch -D %s" % repo): - raise ValueError, "git branch -D %s" % repo - if os.system("git checkout %s" % base): - raise ValueError, "git checkout %s" % base - if os.system("git checkout -b %s" % repo): - raise ValueError, "git checkout -b %s" % repo - if os.system("git pull %s %s" % (repo, repos[repo])): - raise ValueError, 'Incremental pull from repo %s/%s failed.. Trying full operation...' % (repo, repos[repo]) - if os.system("git checkout master"): - raise ValueError, "git checkout master" - if import_([repo]): - raise ValueError, "import_ %s" % repo - kmirrorcheck(None) + repos = {} + if argv: + for i in argv: + a, b = i.split(i.find(':') > 0 and ':' or '/') + if not a or not b: + raise ValueError, "repo syntax error" + repos[a] = b + print 'Checking if a pull from the origin tree is required...' + rev = getorigin() + rev2 = os.popen("git merge-base %s master 2> /dev/null" % rev) + if not rev2 or rev2 == rev: + if os.system("git checkout master"): + raise ValueError, "git checkout master" + if o.system("git pull origin master"): + raise ValueError, "git pull origin master" + if not argv: + rev = os.popen("git rev-parse linux-2.6") + print('Pulling and rebasing to latest linux-2.6 tree') + if os.system("git checkout linux-2.6"): + raise ValueError, "git checkout linux-2.6" + if os.system("git pull --tags linux-2.6 master"): + raise ValueError, "git pull linux-2.6" + if os.system("git push --tags origin linux-2.6:refs/heads/linux-2.6"): + raise ValueError, "git push origin linux-2.6" + rev2 = os.popen("git rev-parse linux-2.6") + if rev != rev2 and os.system("git rebase linux-2.6 master"): + raise ValueError, "git rebase" + for repo in repos: + print('Trying to import patches from %s/%s' % (repo, repos[repo])) + rev = os.popen("git rev-parse %s 2> /dev/null" % repo) + if rev: + if os.system("git checkout %s" % repo): + raise ValueError, "git checkout %s" % repo + if os.system("git pull %s %s" % (repo, repos[repo])): + print('Incremental pull from repo %s/%s failed.. Trying full operation...' % (repo, repos[repo])) + rev = '' + if not rev: + base = os.popen("git merge-base linux-2.6 %s 2> /dev/null" % repo) + print('Merge base %s' % base) + base = base and base or 'linux-2.6' + if os.system("git branch -D %s" % repo): + raise ValueError, "git branch -D %s" % repo + if os.system("git checkout %s" % base): + raise ValueError, "git checkout %s" % base + if os.system("git checkout -b %s" % repo): + raise ValueError, "git checkout -b %s" % repo + if os.system("git pull %s %s" % (repo, repos[repo])): + raise ValueError, 'Incremental pull from repo %s/%s failed.. Trying full operation...' % (repo, repos[repo]) + if os.system("git checkout master"): + raise ValueError, "git checkout master" + if import_([repo]): + raise ValueError, "import_ %s" % repo def compile0(repo): - from dircache import listdir - dir = tmpdir('compile') - os.chdir(dir) - if os.system('rm -rf ' + dir + '/%s*' % package(repo)): - raise ValueError, "rm -rf" - if os.system('LANG=C wget http://www.alsa-project.org/snapshot/?package=%s' % repo): - raise ValueError, "wget" - filename = '' - for f in listdir('.'): - if f.startswith(package(repo) + '-'): - filename = f - break - if not filename: - raise ValueError, "cannot determine filename" - print('Found %s...' % filename) - if os.system('tar xjf %s' % filename): - raise ValueError, "tar xjf %s" % filename - os.chdir(filename[:-8]) - - if not repo in ['alsa-tools', 'alsa-python']: - args = '' - if repo == 'alsa-driver': - args = ' --with-kernel=$HOME/alsa/alsa-kernel' - if os.system("./configure%s" % args): - raise ValueError, "configure" - if not repo in ['alsa-python']: - if os.system("make"): - raise ValueError, "make" - if repo == 'alsa-python': - if os.system("python setup.py build"): - raise ValueError, "build" - if os.system('rm -rf ' + dir + '/%s*' % package(repo)): - raise ValueError, "rm -rf" + from dircache import listdir + dir = tmpdir('compile') + os.chdir(dir) + if os.system('rm -rf ' + dir + '/%s*' % package(repo)): + raise ValueError, "rm -rf" + if os.system('LANG=C wget http://www.alsa-project.org/snapshot/?package=%s' % repo): + raise ValueError, "wget" + filename = '' + for f in listdir('.'): + if f.startswith(package(repo) + '-'): + filename = f + break + if not filename: + raise ValueError, "cannot determine filename" + print('Found %s...' % filename) + if os.system('tar xjf %s' % filename): + raise ValueError, "tar xjf %s" % filename + os.chdir(filename[:-8]) + + if not repo in ['alsa-tools', 'alsa-python']: + args = '' + if repo == 'alsa-driver': + args = ' --with-kernel=$HOME/alsa/alsa-kernel' + if os.system("./configure%s" % args): + raise ValueError, "configure" + if not repo in ['alsa-python']: + if os.system("make"): + raise ValueError, "make" + if repo == 'alsa-python': + if os.system("python setup.py build"): + raise ValueError, "build" + if os.system('rm -rf ' + dir + '/%s*' % package(repo)): + raise ValueError, "rm -rf" def compile(argv=''): - repos = selectrepos(argv) - if 'alsa' in repos: - repos.remove('alsa') - if 'alsa-kmirror' in repos: - repos.remove('alsa-kmirror') - for repo in repos: - compile0(repo) - + repos = selectrepos(argv) + if 'alsa' in repos: + repos.remove('alsa') + if 'alsa-kmirror' in repos: + repos.remove('alsa-kmirror') + for repo in repos: + compile0(repo) + +def dimport(argv=''): + repo = 'alsa-kernel' + branch = 'master' + if argv: + a, b = argv[0].split(i.find(':') > 0 and ':' or '/') + if not a or not b: + raise ValueError, "repo syntax error" + repo = a + branch = b + return driver_merge('alsa-kmirror', 'master', repo, branch) + +def ddiff(argv=''): + repo = 'alsa-kernel' + branch = 'master' + if argv: + a, b = argv[0].split(i.find(':') > 0 and ':' or '/') + if not a or not b: + raise ValueError, "repo syntax error" + repo = a + branch = b + return compare_trees('alsa-kmirror', 'master', repo, branch) + OPTS=[ - ['h', 'help', usage, '', 'Print this help'], - ['r', 'root', root, '', 'Set GIT root directory (default is %s)' % ROOT], - ['v', 'verbose', verbose, '', 'Set verbose mode'] + ['h', 'help', usage, '', 'Print this help'], + ['r', 'root', root, '', 'Set GIT root directory (default is %s)' % config.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'], - ['extpick', extpick, 'local-repo-path commit', 'Pick and merge a patch from another repository'], - ['kmirrorpick', kmirrorpick, 'local-repo-path commit', 'Pick and merge a patch from another repository (kmirror mode)'], - ['edit', edit, 'commit', 'Edit a message for commit'], - ['remove', remove, 'commit', 'Remove a commit'], - ['import', import_, 'branch', 'Import changes from a branch.\nRemove duplicate patches.'], - ['kmirrorcheck', kmirrorcheck, '[full]', 'Check for already merged patches and fill git-ok-commits file.'], - ['kmirrormark', kmirrormark, 'commit', 'Mark already merged patch to git-ok-commits file.'], - ['kimport', kimport, '[remote/branch]', 'Import changes from Linus and Takashi to alsa-kernel.git.\nOr import changes from specified repository.'], - ['tolinus', tolinus, 'branch', 'Send a merge request for given branch to linus'], - ['compile', compile, '', 'Compile all ALSA packages from actual snapshot (compilation test)'] + ['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'], + ['extpick', extpick, 'local-repo-path commit', 'Pick and merge a patch from another repository'], + ['kmirrorpick', kmirrorpick, 'local-repo-path commit', 'Pick and merge a patch from another repository (kmirror mode)'], + ['edit', edit, 'commit', 'Edit a message for commit'], + ['remove', remove, 'commit', 'Remove a commit'], + ['import', import_, 'branch', 'Import changes from a branch.\nRemove duplicate patches.'], + ['kimport', kimport, '[remote/branch]', 'Import changes from Linus and Takashi to alsa-kernel.git.\nOr import changes from specified repository.'], + ['dimport', dimport, '[remote/branch]', 'Import changes to alsa-kmirror tree.'], + ['ddiff', ddiff, '[remote/branch]', 'Show diff between alsa-kmirror tree and specified repo/branch.'], + ['tolinus', tolinus, 'branch', 'Send a merge request for given branch to linus'], + ['compile', compile, '', 'Compile all ALSA packages from actual snapshot (compilation test)'] ] def main(): - global ROOT - if os.path.exists(ROOT + '/../alsa-driver'): - 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]) + global ROOT + if os.path.exists(config.ROOT + '/../alsa-driver'): + config.ROOT = os.path.abspath(config.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) + main() + sys.exit(0) diff --git a/comments.py b/comments.py index e381c18..b20587c 100644 --- a/comments.py +++ b/comments.py @@ -170,6 +170,7 @@ COMMENT_MAP = { ['/pci/cs5530.c', 'CS5530 Cyrix/NatSemi VSA1 softaudio init'], ['/pci/oxygen/.*', 'CMI8788 (Oxygen) driver'], ['/pci/aw2/.*', 'Emagic Audiowerk 2'], + ['/pci/lx6464es/.*', 'LX6464ES'], ['/pci', 'ERROR'], ['/ppc/Makefile', 'PPC'], ['/ppc/Kconfig', 'PPC'], @@ -178,6 +179,7 @@ COMMENT_MAP = { ['/ppc/daca.c', 'PPC DACA driver'], ['/ppc/keywest.c', 'PPC Keywest driver'], ['/ppc/keywest_old.c', 'PPC Keywest driver'], + ['/ppc/keywest_old_i2c.c', 'PPC Keywest driver'], ['/ppc/pmac.(c|h|inc|patch)', 'PPC PMAC driver'], ['/ppc/pmac_old.c', 'PPC PMAC driver'], ['/ppc/powermac.c', 'PPC PowerMac driver'], @@ -246,6 +248,7 @@ COMMENT_MAP = { ['/soc/codecs/l3.(c|h)', 'SoC L3 bus'], ['/soc/codecs/ac97.(c|h)', 'SoC Codec AC97'], ['/soc/codecs/wm8350.(c|h)', 'SoC Codec WM8350'], + ['/soc/codecs/wm8400.(c|h)', 'SoC Codec WM8400'], ['/soc/codecs/wm8510.(c|h)', 'SoC Codec WM8510'], ['/soc/codecs/wm8560.(c|h)', 'SoC Codec WM8560'], ['/soc/codecs/wm8580.(c|h)', 'SoC Codec WM8580'], @@ -267,6 +270,7 @@ COMMENT_MAP = { ['/soc/codecs/tlv320aic3x.(c|h)', 'SoC Codec TLV320AIC3X'], ['/soc/codecs/uda134x.(c|h)', 'SoC Codec Philips UDA134x'], ['/soc/codecs/uda1380.(c|h)', 'SoC Codec Philips UDA1380'], + ['/soc/codecs/ak4104.(c|h)', 'SoC Codec AK4104'], ['/soc/codecs/ak4535.(c|h)', 'SoC Codec AK4535'], ['/soc/codecs/ssm2602.(c|h)', 'SoC Codec SSM2602'], ['/soc/codecs/ad73311.(c|h)', 'SoC Codec AD73311'], @@ -285,7 +289,10 @@ COMMENT_MAP = { ['/soc/pxa/em-x270*', 'SoC PXA2xx EM-X270'], ['/soc/pxa/palm27x*', 'SoC PXA2xx Palm T|X, T5 and LifeDrive'], ['/soc/pxa/zylonite*', 'SoC PXA2xx Zylonite'], + ['/soc/pxa/e740_wm9705.c', 'SoC PXA2xx E740'], ['/soc/pxa/e750_wm9705.c', 'SoC PXA2xx E750'], + ['/soc/pxa/mioa701_wm9713.c', 'SoC PXA2xx MIOA701'], + ['/soc/pxa/magician.c', 'Soc PXA2xx Magician'], ['/soc/pxa/Kconfig', 'SoC PXA2xx Core'], ['/soc/s3c24xx/.*', 'SoC Audio for the Samsung S3C24XX chips'], ['/soc/sh/.*', 'SoC SH7760 AC97'], @@ -294,6 +301,7 @@ COMMENT_MAP = { ['/soc/omap/.*', 'SoC Texas Instruments OMAP'], ['/soc/au1x/.*', 'Au12x0/Au1550 PSC ASoC'], ['/soc/blackfin/.*', 'SoC Blackfin'], + ['/soc/s6000/.*', 'SoC S6000'], ['/soc/soc-core.*', 'SoC Layer'], ['/soc/soc-jack.*', 'SoC Layer'], ['/soc/Kconfig', 'SoC Layer'], @@ -310,6 +318,9 @@ COMMENT_MAP = { ['/usb/usbmixer_maps.c', 'USB generic driver'], ['/usb/usbcompat.h', 'USB generic driver'], ['/usb', 'ERROR'], + ['/include/atmel-abdac.h', 'Atmel on-chip Audio Bitstream DAC (ABDAC)'], + ['/include/atmel-ac97c.h', 'Atmel on-chip Audio Bitstream DAC (ABDAC)'], + ['/atmel/.*', 'Atmel on-chip Audio Bitstream DAC (ABDAC)'], ['/include/hal2.h', 'HAL2 driver'], ['/hal2/.*', 'HAL2 driver'], ['/aoa/.*', 'Apple Onboard Audio driver'], @@ -554,6 +565,8 @@ COMMENT_MAP = { ['/pph/.*', 'Public Parrot Hack rate converter'], ['/rate-lavc/.*', "libavcodec's resampler"], ['/usb_stream/.*', 'USB stream plugin'], + ['/speex/.*', 'Speex PCM plugin'], + ['/arcam-av/.*', 'Arcam AV control plugin'], ['/m4/.*', 'Core'], ['/COPYING.GPL', 'Core'], ['/COPYING', 'Core'], diff --git a/config.py b/config.py new file mode 100644 index 0000000..d9c9dae --- /dev/null +++ b/config.py @@ -0,0 +1,34 @@ +#! /usr/bin/python +# -*- Python -*- + +import os + +ROOT = os.path.abspath(os.getcwd()) +USER = os.getenv('USER') +VERBOSE = False +GERRORS = 0 +TMPDIR = '/dev/shm/alsatool' +GIT_KERNEL_MERGE = 'v2.6.29' +GIT_DRIVER_MERGE = 'v1.0.18' +REPOSITORIES = [ + 'alsa', 'alsa-driver', 'alsa-kmirror', 'alsa-lib', 'alsa-utils', + 'alsa-tools', 'alsa-firmware', 'alsa-oss', 'alsa-plugins', + 'alsa-python' +] +ALSA_FILES = ( + 'Documentation/sound/alsa/', + 'sound/', + 'include/sound/' +) +NOT_ALSA_FILES = ( + 'sound/oss/', +) +ALSA_TRANSLATE = { + 'Documentation/DocBook/alsa-driver-api.tmpl': 'Documentation/DocBook/alsa-driver-api.tmpl', + 'Documentation/sound/alsa/': 'Documentation/', + 'include/sound/': 'include/', + 'sound/': '' +} +ALSA_RTRANSLATE = {} +for i in ALSA_TRANSLATE: + ALSA_RTRANSLATE[ALSA_TRANSLATE[i]] = i diff --git a/drivermerge.py b/drivermerge.py new file mode 100644 index 0000000..753ebef --- /dev/null +++ b/drivermerge.py @@ -0,0 +1,400 @@ +#!/usr/bin/python + +import config +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 +from utils import git_popen, git_system, git_repo, is_alsa_file, to_alsa_file, \ + tmpfile, tmpdir, diff_compare2, to_kernel_file, \ + git_read_commits, raw_subject +import re + +def error(lines, msg, *args): + for line in lines: + stderr.write('===> %s' % line) + stderr.write('ERROR: ' + msg % args) + +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 + return True + +def analyze_diff(fp, full=False, filter_git=False): + rlines = [] + ok = False + addfiles = [] + rmfiles = [] + start = True + while 1: + line = fp.readline() + if not line: + break + if filter_git and line.startswith('index ') and line.find('..') > 0: + continue + if line.startswith('diff --git a/'): + start = False + file1, file2 = line[11:].split(' ') + file1 = file1.strip() + file2 = file2.strip() + ok1 = is_alsa_file(file1[2:]) + ok2 = is_alsa_file(file2[2:]) + ok = False + 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)) + addfiles.append(to_alsa_file(file1, 'a/')[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 and line.startswith('+++ /dev/null'): + spec = to_alsa_file(file1, 'a/')[2:] + rmfiles.append(spec) + addfiles.remove(spec) + rlines.append(line) + elif ok or (full and start): + rlines.append(line) + fp.close() + return rlines, addfiles, rmfiles + +def commit_is_merged(commit, driver_commits): + lines = commit['comment'].splitlines() + subj = raw_subject(lines[0]) + for commit2 in driver_commits: + lines2 = commit2['comment'].splitlines() + if subj == raw_subject(lines2[0]): + return True + return False + +def commit_is_merged_diff(driver_repo, kernel_repo, commit): + ok = True + for f in commit['files']: + if not is_alsa_file(f): + continue + a = to_alsa_file(f) + lines = popen("diff -u %s %s 2> /dev/null" % (git_repo(driver_repo) + '/' + a, git_repo(kernel_repo) + '/' + f)).readlines() + if lines: + ok = False + break + return ok + +def try_to_merge(driver_repo, driver_branch, kernel_repo, commit): + comment = commit['comment'].splitlines() + ref = commit['ref'] + + print 'Merging %s %s' % (ref[:7], comment[0]) + + fp = git_popen(kernel_repo, "diff %s~1..%s" % (ref, ref)) + rlines, addfiles, rmfiles = analyze_diff(fp) + fp.close() + + patchfile = tmpfile('alsa-kmirror-patch') + fp = open(patchfile, 'w+') + fp.write(''.join(rlines)) + fp.close() + + commentfile = tmpfile('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() + if git_system(driver_repo, "checkout -q %s" % driver_branch): + raise ValueError, 'git checkout' + chdir(git_repo(driver_repo)) + lines = popen("LANG=C patch -f -p 1 --dry-run --global-reject-file=%s < %s" % (tmpfile("rejects"), patchfile)).readlines() + failed = fuzz = succeed = 0 + for line in lines: + if line.find('FAILED') >= 0: + failed += 1 + if line.find('succeed') >= 0: + if line.find('fuzz') >= 0: + fuzz += 1 + else: + succeed += 1 + if failed: + print 'Merge skipped %s %s (%s failed)' % (ref[:7], comment[0], failed) + chdir(curdir) + return False + if git_system(driver_repo, "apply --check %s" % patchfile): + print 'Merge skipped %s %s (apply check)' % (ref[:7], comment[0]) + chdir(curdir) + return False + if git_system(driver_repo, "apply %s" % patchfile): + chdir(curdir) + raise ValueError, 'git apply' + if addfiles and git_system(driver_repo, "add %s" % ' '.join(addfiles)): + chdir(curdir) + raise ValueError, 'git add' + if rmfiles and git_system(driver_repo, "rm %s" % ' '.join(rmfiles)): + chdir(curdir) + raise ValueError, 'git rm' + if git_system(driver_repo, "commit -F %s" % commentfile, exports=exports): + chdir(curdir) + raise ValueError, 'git commit' + chdir(curdir) + + print 'Merge complete %s %s (%s fuzz)' % (ref[:7], comment[0], fuzz) + return True + +def try_to_merge_hard(driver_repo, driver_branch, kernel_repo, kernel_branch, commit): + ref = commit['ref'] + fp = git_popen(kernel_repo, "diff %s~1..%s" % (ref, ref)) + rlines, addfiles, rmfiles = analyze_diff(fp) + fp.close() + patchfile = tmpfile('alsa-kmirror-patch') + fp = open(patchfile, 'w+') + fp.write(''.join(rlines)) + fp.close() + curdir = getcwd() + chdir(git_repo(driver_repo)) + lines = git_popen(driver_repo, "apply -v --check %s 2>&1" % patchfile).readlines() + patch = plines = None + for line in lines: + if line.startswith('Checking patch '): + patch = line[15:-4] + plines = None + elif line == 'error: while searching for:\n': + plines = [] + elif line.startswith('error: '): + if patch and plines is not None: + break + patch = plines = None + else: + if plines is not None: + plines.append(line) + if not patch and not plines: + return False + chdir(git_repo(kernel_repo)) + lines = git_popen(kernel_repo, "annotate %s %s" % (to_kernel_file(patch), ref)).readlines() + start = end = None + idx = -1 + missing = plines[:] + missingrefs = [] + for line in lines: + idx += 1 + pos = line.find('\t') + if pos < 0: + continue + hash = line[:pos] + pos = line.find(')') + if pos < 0: + continue + code = line[pos+1:] + if code in missing: + missing.remove(code) + if start is None: + start = idx + end = idx + elif start is not None: + missing.append(code) + if start is None: + return False + for idx in range(max(0, start-1), min(len(lines), end+2)): + line = lines[idx] + pos = line.find('\t') + if pos < 0: + continue + hash = line[:pos] + if hash == ref[:8]: + continue + pos = line.find(')') + if pos < 0: + continue + code = line[pos+1:] + for m in missing: + if code == m: + if not hash in missingrefs: + missingrefs.append(hash) + chdir(curdir) + ok = False + for mref in missingrefs: + commits = git_read_commits(kernel_repo, mref + "~1", mref) + if commits and try_to_merge(driver_repo, driver_branch, kernel_repo, commits[0]): + ok = True + return ok + +def compare_trees(driver_repo, driver_branch, kernel_repo, kernel_branch): + print 'comparing %s/%s (old) and %s/%s (new) repos' % (driver_repo, driver_branch, kernel_repo, kernel_branch) + worktree = tmpdir('alsa-kmirror-repo') + worktreek = tmpdir('alsa-kernel-repo') + rmtree(worktree, ignore_errors=True) + rmtree(worktreek, ignore_errors=True) + mkdir(worktree) + mkdir(worktreek) + if git_system(driver_repo, "archive --format=tar %s | tar xf - -C %s" % (driver_branch, worktree)): + raise ValueError, 'git export (kmirror)' + if git_system(kernel_repo, "archive --format=tar %s sound include/sound Documentation/DocBook Documentation/sound/alsa | tar xf - -C %s" % (kernel_branch, worktreek)): + raise ValueError, 'git export (kernel)' + git_system(driver_repo, "checkout %s" % driver_branch) + git_system(kernel_repo, "checkout %s" % kernel_branch) + curdir = getcwd() + chdir(tmpdir()) + 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") + system("mv alsa-kernel-repo/Documentation/DocBook/alsa-driver-api.tmpl alsa-kernel-repo/Documentation") + rmtree("alsa-kernel-repo/Documentation/sound") + rmtree("alsa-kernel-repo/Documentation/DocBook") + mkdir("alsa-kernel-repo/Documentation/DocBook") + system("mv alsa-kernel-repo/Documentation/alsa-driver-api.tmpl alsa-kernel-repo/Documentation/DocBook") + 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', 'pci/ac97/ak4531_codec.c', 'isa/sb/sb16_csp_codecs.h', + 'pci/korg1212/korg1212-firmware.h', 'pci/ymfpci/ymfpci_image.h', + 'pci/hda/hda_patch.h', + 'isa/ad1848/ad1848_lib.c', 'isa/cs423x/cs4231_lib.c', 'isa/cs423x/cs4232.c', + 'include/cs4231.h', 'soc/at91/eti_b1_wm8731.c', + 'aoa/codecs/snd-aoa-codec-onyx.c', 'aoa/codecs/snd-aoa-codec-onyx.h', + 'aoa/codecs/snd-aoa-codec-tas-basstreble.h', 'aoa/codecs/snd-aoa-codec-tas-gain-table.h', + 'aoa/codecs/snd-aoa-codec-tas.c', 'sound/aoa/codecs/snd-aoa-codec-tas.h', + 'aoa/codecs/snd-aoa-codec-toonie.c', 'aoa/core/snd-aoa-alsa.c', + 'aoa/core/snd-aoa-alsa.h', 'aoa/core/snd-aoa-core.c', + 'aoa/core/snd-aoa-gpio-feature.c', 'aoa/core/snd-aoa-gpio-pmf.c', + 'aoa/fabrics/snd-aoa-fabric-layout.c', 'aoa/soundbus/i2sbus/i2sbus-control.c', + 'aoa/soundbus/i2sbus/i2sbus-core.c', 'aoa/soundbus/i2sbus/i2sbus-interface.h', + 'aoa/soundbus/i2sbus/i2sbus-pcm.c', 'aoa/codecs/snd-aoa-codec-tas.h', + 'include/uda1341.h', 'i2c/l3/', 'arm/sa11xx-uda1341.c', + 'soc/at91/', 'soc/at32/', + 'usb/caiaq/caiaq-audio.c', 'usb/caiaq/caiaq-audio.h', + 'usb/caiaq/caiaq-control.c', 'usb/caiaq/caiaq-control.h', + 'usb/caiaq/caiaq-device.c', 'usb/caiaq/caiaq-device.h', + 'usb/caiaq/caiaq-input.c', 'usb/caiaq/caiaq-input.h', + 'usb/caiaq/caiaq-midi.c', 'usb/caiaq/caiaq-midi.h', + 'isa/wavefront/yss225.c' + ]: + 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 + stdout.write(line) + notempty = True + if notempty: + stdout.write('\n') + rmtree(worktree, ignore_errors=True) + rmtree(worktreek, ignore_errors=True) + if notempty: + stderr.write('repositories does not match, please, fix it\n') + return False + return True + +def commit_is_merged_hard(kernel_repo, commit, driver_repo, driver_commits): + ref = commit['ref'] + fp = git_popen(kernel_repo, "diff %s~1..%s" % (ref, ref)) + rlines, addfiles, rmfiles = analyze_diff(fp) + fp.close() + files = addfiles + rmfiles + for dc in driver_commits: + ok = True + for f in files: + if not f in dc['files']: + ok = False + break + if ok: + ref1 = dc['ref'] + curdir = getcwd() + chdir(git_repo(driver_repo)) + fp = git_popen(driver_repo, "diff %s~1..%s %s" % (ref1, ref1, ' '.join(files))) + chdir(curdir) + lines = fp.readlines() + fp.close() + #print 'Candidate', dc['ref'][:7], dc['comment'].splitlines()[0] + #if ref1[:7] == 'd26326d': + # open("/dev/shm/aaa.1", "w+").write(''.join(lines)) + # open("/dev/shm/aaa.2", "w+").write(''.join(rlines)) + if diff_compare2(lines, rlines): + return dc + return None + +def driver_merge(driver_repo, driver_branch, kernel_repo, kernel_branch): + if git_system(driver_repo, "checkout -q %s" % driver_branch): + raise ValueError, 'git checkout' + if git_system(kernel_repo, "checkout -q %s" % kernel_branch): + raise ValueError, 'git checkout' + driver_commits = git_read_commits(driver_repo, config.GIT_DRIVER_MERGE, driver_branch) + kernel_commits = git_read_commits(kernel_repo, config.GIT_KERNEL_MERGE, kernel_branch, kernel_tree=True) + if not driver_commits or not kernel_commits: + print 'Nothing to do' + return + print 'Analyzing merged commits:' + remove = [] + for commit in reversed(kernel_commits): + if commit_is_merged(commit, driver_commits): + remove.append(commit) + elif commit_is_merged_diff(driver_repo, kernel_repo, commit): + remove.append(commit) + print ' %s commits are already merged' % len(remove) + ok = [] + for commit in reversed(kernel_commits): + if commit in remove: + continue + if try_to_merge(driver_repo, driver_branch, kernel_repo, commit): + ok.append(commit) + print '*** %s merged %s already merged %s remaining' % (len(ok), len(remove), len(kernel_commits)-len(remove)-len(ok)) + failed = [] + for commit in reversed(kernel_commits): + if commit in remove or commit in ok: + continue + if commit_is_merged_diff(driver_repo, kernel_repo, commit): + print 'NOCHANGE: %s %s' % (commit['ref'][:7], commit['comment'].splitlines()[0]) + continue + res = commit_is_merged_hard(kernel_repo, commit, driver_repo, driver_commits) + if res: + print ' HARD : %s %s' % (commit['ref'][:7], commit['comment'].splitlines()[0]) + print ' : in commit %s %s' % (res['ref'][:7], res['comment'].splitlines()[0]) + continue + else: + failed.append(commit) + #else: + # if not try_to_merge_hard(driver_repo, driver_branch, kernel_repo, kernel_branch, commit): + # failed.append(commit) + # else: + # print ' HARDM : %s %s' % (commit['ref'][:7], commit['comment'].splitlines()[0]) + if failed: + print ' *********' + for commit in failed: + print ' FAILED: %s %s' % (commit['ref'][:7], commit['comment'].splitlines()[0]) + +if __name__ == '__main__': + driver_merge('alsa-kmirror', 'master', 'alsa-kernel', 'tiwai-fornext') + #compare_trees('alsa-kmirror', 'master', 'alsa-kernel', 'tiwai-fornext') + #print try_to_merge_hard('alsa-kmirror', 'master', + # 'alsa-kernel', 'tiwai-fornext', + # git_read_commits('alsa-kernel', + # '5409fb4e327a84972483047ecf4fb41f279453e2~1', + # '5409fb4e327a84972483047ecf4fb41f279453e2')[0]) diff --git a/hooks/alsa-kernel.git/pre-receive b/hooks/alsa-kernel.git/pre-receive deleted file mode 100755 index c4d4ec2..0000000 --- a/hooks/alsa-kernel.git/pre-receive +++ /dev/null @@ -1,471 +0,0 @@ -#!/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 - -# do not merge new patches -# ignore new patches for alsa-kmirror -DO_NOT_MERGE = False -# do not fail when trees does not match -# just inform users that alsa-kmirror is different -DO_NOT_FAIL = False -# enable (set this to True) if you like to skip pre-receive checks -# do it only when really necessary after discussed in ALSA committer group -# this option turns this whole script off -DO_NOT_CHECK = False - -TMP_PATH = '/dev/shm' - -REPO_DIR = '/home/alsa-server/home/repositories' -ALSA_REPO = REPO_DIR + '/alsa.git' -KMIRROR_REPO = REPO_DIR + '/alsa-kmirror.git' -KERNEL_REPO = REPO_DIR + '/alsa-kernel.git' - -VALID_COMMITERS = ( - 'Jaroslav Kysela ', - 'Takashi Iwai ', - 'Clemens Ladisch ', - 'James Courtier-Dutton ', - 'Linus Torvalds ', - 'Mark Brown ', -) - -ALSA_FILES = ( - 'Documentation/sound/alsa/', - 'sound/', - 'include/sound/' -) - -NOT_ALSA_FILES = ( -# 'sound/sound_core.c', -# 'sound/sound_firmware.c', - 'sound/oss/', -) - -ALSA_FILES1 = { - 'Documentation/DocBook/alsa-driver-api.tmpl': 'Documentation/DocBook/alsa-driver-api.tmpl', - '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 "refs/heads/broken" HEAD' % KMIRROR_REPO): - raise ValueError, "update-ref failed" - stderr.write('PRE-RECEIVE: alsa-kmirror.git problematic HEAD is in branch named "broken"\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:'): - line = line.replace('Signed-off-by:', '') - a, b = line.split(': ') - commit[a.strip()] = b.strip() - if commitref: - ALSA_COMMITS[commitref] = commit - fp.close() - - worktree = TMP_PATH + '/alsa-repo' - rmtree(worktree, ignore_errors=True) - mkdir(worktree) - if system("git --work-tree=%s --git-dir=%s checkout -q master kernel-sync" % (worktree, ALSA_REPO)): - raise ValueError, 'git checkout' - if exists(worktree + '/kernel-sync/git-ok-commits'): - fp = open(worktree + '/kernel-sync/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:]) - ok = False - 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)) - addfiles.append(to_alsa_file(file1, 'a/')[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 and line.startswith('+++ /dev/null'): - spec = to_alsa_file(file1, 'a/')[2:] - rmfiles.append(spec) - addfiles.remove(spec) - rlines.append(line) - 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.git/kernel-sync/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'])) - error([], 'Patch: %s %s' % (commit['commit'][:7], commit['comment'][0])) - chdir(curdir) - rmtree(worktree, ignore_errors=True) - stderr.write('PRE-RECEIVE: Merge skipped %s %s' % (ref[:7], commit['comment'][0])) - return - 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 = line.split(': ') - commit[a[0].strip()] = ': '.join(a[1:]).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: ') and \ - not lines[6][4:].upper().startswith('ASOC: ') and \ - not lines[6][4:].upper().startswith('[SOUND] ') and \ - not lines[6][4:].upper().startswith('SOUND: '): - error(lines, 'First log line does not start with "[ALSA] " or "ALSA: " or "[SOUND] " or "SOUND: "\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/DocBook 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") - system("mv alsa-kernel-repo/Documentation/DocBook/alsa-driver-api.tmpl alsa-kernel-repo/Documentation") - rmtree("alsa-kernel-repo/Documentation/sound") - rmtree("alsa-kernel-repo/Documentation/DocBook") - system("mkdir alsa-kernel-repo/Documentation/DocBook") - system("mv alsa-kernel-repo/Documentation/alsa-driver-api.tmpl alsa-kernel-repo/Documentation/DocBook") - 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', 'pci/ac97/ak4531_codec.c', 'isa/sb/sb16_csp_codecs.h', - 'pci/korg1212/korg1212-firmware.h', 'pci/ymfpci/ymfpci_image.h', - 'pci/hda/hda_patch.h', - 'isa/ad1848/ad1848_lib.c', 'isa/cs423x/cs4231_lib.c', 'isa/cs423x/cs4232.c', - 'include/cs4231.h', 'soc/at91/eti_b1_wm8731.c', - 'aoa/codecs/snd-aoa-codec-onyx.c', 'aoa/codecs/snd-aoa-codec-onyx.h', - 'aoa/codecs/snd-aoa-codec-tas-basstreble.h', 'aoa/codecs/snd-aoa-codec-tas-gain-table.h', - 'aoa/codecs/snd-aoa-codec-tas.c', 'sound/aoa/codecs/snd-aoa-codec-tas.h', - 'aoa/codecs/snd-aoa-codec-toonie.c', 'aoa/core/snd-aoa-alsa.c', - 'aoa/core/snd-aoa-alsa.h', 'aoa/core/snd-aoa-core.c', - 'aoa/core/snd-aoa-gpio-feature.c', 'aoa/core/snd-aoa-gpio-pmf.c', - 'aoa/fabrics/snd-aoa-fabric-layout.c', 'aoa/soundbus/i2sbus/i2sbus-control.c', - 'aoa/soundbus/i2sbus/i2sbus-core.c', 'aoa/soundbus/i2sbus/i2sbus-interface.h', - 'aoa/soundbus/i2sbus/i2sbus-pcm.c', 'aoa/codecs/snd-aoa-codec-tas.h', - 'include/uda1341.h', 'i2c/l3/', 'arm/sa11xx-uda1341.c', - 'soc/at91/', 'soc/at32/', - 'usb/caiaq/caiaq-audio.c', 'usb/caiaq/caiaq-audio.h', - 'usb/caiaq/caiaq-control.c', 'usb/caiaq/caiaq-control.h', - 'usb/caiaq/caiaq-device.c', 'usb/caiaq/caiaq-device.h', - 'usb/caiaq/caiaq-input.c', 'usb/caiaq/caiaq-input.h', - 'usb/caiaq/caiaq-midi.c', 'usb/caiaq/caiaq-midi.h', - 'isa/wavefront/yss225.c' - ]: - 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') - if not DO_NOT_FAIL: - fail() - return False - return True - -if DO_NOT_CHECK: - exit(0) -lines = stdin.readlines() -lastref = '' -for line in lines: - sha1old, sha1new, refname = line[:-1].split(' ') - if refname in ['refs/heads/linux-2.6', 'refs/heads/for-linus', - 'refs/heads/linux-next']: - continue - elif refname.startswith('refs/tags/') or \ - refname.startswith('refs/heads/stable-2.6.'): - continue - elif refname != 'refs/heads/master': - stderr.write('PRE-RECEIVE: invalid branch "%s"\n' % refname) - fail() - if not DO_NOT_MERGE: - if not lastref: - read_upstream_commits(lines[0][:-1].split(' ')[0]) - do_check(sha1old, sha1new, refname) - lastref = sha1new -if lastref: - if not 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) diff --git a/kernel-sync/git-ok-commits b/kernel-sync/git-ok-commits deleted file mode 100644 index 8c2823d..0000000 --- a/kernel-sync/git-ok-commits +++ /dev/null @@ -1,845 +0,0 @@ -# This is a special file which contains references to alsa-kernel.git -# used to verify if a given commit is already in the alsa-kmirror.git -# tree. -# -# 1st column - author name and e-mail (like from git log) -# 2nd column - author date (iso format) -# 3rd column - commiter name and e-mail (like from git log) -# 4th column - commit date (iso format) -# -"Alexey Dobriyan " "2008-04-29 01:01:44 -0700" "Linus Torvalds " "2008-04-29 08:06:18 -0700" -"Denis V. Lunev " "2008-04-29 01:02:13 -0700" "Linus Torvalds " "2008-04-29 08:06:20 -0700" -"Hirofumi Nakagawa " "2008-04-29 01:03:09 -0700" "Linus Torvalds " "2008-04-29 08:06:25 -0700" -"Takashi Iwai " "2008-04-25 09:13:45 +0200" "Takashi Iwai " "2008-04-29 19:01:56 +0200" -"Takashi Iwai " "2008-04-25 09:15:12 +0200" "Takashi Iwai " "2008-04-29 19:01:56 +0200" -"Jarkko Nikula " "2008-04-25 13:55:19 +0200" "Takashi Iwai " "2008-04-29 19:01:56 +0200" -"Takashi Iwai " "2008-04-25 15:25:04 +0200" "Takashi Iwai " "2008-04-29 19:01:57 +0200" -"Takashi Iwai " "2008-04-28 12:35:41 +0200" "Takashi Iwai " "2008-04-29 19:01:57 +0200" -"Mark Brown " "2008-04-28 14:15:28 +0100" "Takashi Iwai " "2008-04-29 19:01:57 +0200" -"Mark Brown " "2008-04-30 17:18:43 +0200" "Takashi Iwai " "2008-04-30 19:37:39 +0200" -"Mark Brown " "2008-04-30 17:19:07 +0200" "Takashi Iwai " "2008-04-30 19:37:47 +0200" -"Mark Brown " "2008-04-30 17:19:32 +0200" "Takashi Iwai " "2008-04-30 19:37:55 +0200" -"Mark Brown " "2008-04-30 17:19:57 +0200" "Takashi Iwai " "2008-04-30 19:38:06 +0200" -"Graeme Gregory " "2008-04-30 20:24:54 +0200" "Takashi Iwai " "2008-04-30 19:38:18 +0200" -"Graeme Gregory " "2008-04-30 20:25:23 +0200" "Takashi Iwai " "2008-04-30 19:38:26 +0200" -"Graeme Gregory " "2008-04-30 20:26:45 +0200" "Takashi Iwai " "2008-04-30 19:38:34 +0200" -"Johann Felix Soden " "2008-05-02 09:54:31 +0200" "Takashi Iwai " "2008-05-05 14:12:07 +0200" -"Takashi Iwai " "2008-05-02 12:28:02 +0200" "Takashi Iwai " "2008-05-05 14:12:07 +0200" -#"Takashi Iwai " "2008-05-02 12:31:51 +0200" "Takashi Iwai " "2008-05-05 14:12:08 +0200" -"Jacek Luczak " "2008-05-03 18:41:23 +0200" "Takashi Iwai " "2008-05-05 14:12:08 +0200" -"Takashi Iwai " "2008-05-03 18:46:56 +0200" "Takashi Iwai " "2008-05-05 14:12:08 +0200" -"Davide Rizzo " "2008-05-05 14:56:07 +0200" "Takashi Iwai " "2008-05-05 14:12:08 +0200" -"Davide Rizzo " "2008-05-05 14:59:39 +0200" "Takashi Iwai " "2008-05-05 14:12:08 +0200" -#"Stas Sergeev " "2008-05-07 12:39:56 +0200" "Takashi Iwai " "2008-05-07 12:42:03 +0200" -"Mark Brown " "2008-05-08 14:03:30 +0200" "Takashi Iwai " "2008-05-08 13:08:54 +0200" -"Patrik Sevallius " "2008-05-08 14:04:08 +0200" "Takashi Iwai " "2008-05-08 13:08:58 +0200" -"maximilian attems " "2008-05-09 13:43:09 +0200" "Takashi Iwai " "2008-05-13 14:47:43 +0200" -"Anton Vorontsov " "2008-05-09 13:43:55 +0200" "Takashi Iwai " "2008-05-13 14:47:43 +0200" -"Jarkko Nikula " "2008-05-09 15:05:41 +0200" "Takashi Iwai " "2008-05-13 14:47:43 +0200" -"Philipp Zabel " "2008-05-13 14:03:40 +0200" "Takashi Iwai " "2008-05-13 14:47:44 +0200" -"Jarkko Nikula " "2008-05-13 16:02:04 +0200" "Takashi Iwai " "2008-05-13 15:15:58 +0200" -"Sebastian Siewior " "2008-04-25 08:29:05 +0200" "Jaroslav Kysela " "2008-05-19 12:55:45 +0200" -"Sebastian Siewior " "2008-04-25 08:29:05 +0200" "Jaroslav Kysela " "2008-05-19 13:17:06 +0200" -"Daniel Mack " "2008-04-30 16:20:19 +0200" "Jaroslav Kysela " "2008-05-19 13:19:13 +0200" -"Daniel Mack " "2008-04-30 16:20:52 +0200" "Jaroslav Kysela " "2008-05-19 13:19:14 +0200" -"Graeme Gregory " "2008-04-30 19:27:40 +0200" "Jaroslav Kysela " "2008-05-19 13:19:14 +0200" -"Stephen Rothwell " "2008-05-01 10:49:18 +0200" "Jaroslav Kysela " "2008-05-19 13:19:14 +0200" -"Tim Niemeyer " "2008-05-05 14:16:12 +0200" "Jaroslav Kysela " "2008-05-19 13:19:14 +0200" -"Daniel Jacobowitz " "2008-05-07 12:05:10 +0200" "Jaroslav Kysela " "2008-05-19 13:19:14 +0200" -"Harvey Harrison " "2008-05-08 13:01:32 +0200" "Jaroslav Kysela " "2008-05-19 13:19:15 +0200" -"Daniel Mack " "2008-05-08 15:42:15 +0200" "Jaroslav Kysela " "2008-05-19 13:19:15 +0200" -"Takashi Iwai " "2008-05-09 12:45:56 +0200" "Jaroslav Kysela " "2008-05-19 13:19:15 +0200" -"Clemens Ladisch " "2008-05-13 09:18:27 +0200" "Jaroslav Kysela " "2008-05-19 13:19:15 +0200" -"Clemens Ladisch " "2008-05-13 09:19:53 +0200" "Jaroslav Kysela " "2008-05-19 13:19:15 +0200" -"Clemens Ladisch " "2008-05-13 09:20:51 +0200" "Jaroslav Kysela " "2008-05-19 13:19:16 +0200" -"Clemens Ladisch " "2008-05-13 09:21:48 +0200" "Jaroslav Kysela " "2008-05-19 13:19:16 +0200" -"Clemens Ladisch " "2008-05-13 09:22:43 +0200" "Jaroslav Kysela " "2008-05-19 13:19:17 +0200" -"Clemens Ladisch " "2008-05-13 09:23:02 +0200" "Jaroslav Kysela " "2008-05-19 13:19:17 +0200" -"Clemens Ladisch " "2008-05-13 09:24:39 +0200" "Jaroslav Kysela " "2008-05-19 13:19:17 +0200" -"Clemens Ladisch " "2008-05-13 09:25:39 +0200" "Jaroslav Kysela " "2008-05-19 13:19:17 +0200" -"Mark Brown " "2008-05-13 14:51:19 +0200" "Jaroslav Kysela " "2008-05-19 13:19:18 +0200" -"Mark Brown " "2008-05-13 14:52:19 +0200" "Jaroslav Kysela " "2008-05-19 13:19:18 +0200" -"Mark Brown " "2008-05-13 14:55:22 +0200" "Jaroslav Kysela " "2008-05-19 13:19:18 +0200" -"Mark Brown " "2008-05-13 14:55:48 +0200" "Jaroslav Kysela " "2008-05-19 13:19:18 +0200" -"Mark Brown " "2008-05-13 14:57:37 +0200" "Jaroslav Kysela " "2008-05-19 13:19:18 +0200" -"Mark Brown " "2008-05-13 14:58:03 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Mark Brown " "2008-05-13 14:58:30 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Mark Brown " "2008-05-13 14:58:57 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Jarkko Nikula " "2008-05-15 11:01:36 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Andreas Mohr " "2008-05-16 12:18:29 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Takashi Iwai " "2008-05-16 12:34:47 +0200" "Jaroslav Kysela " "2008-05-19 13:19:19 +0200" -"Mark Brown " "2008-05-19 12:30:58 +0200" "Jaroslav Kysela " "2008-05-19 13:19:20 +0200" -"Mark Brown " "2008-05-19 12:31:55 +0200" "Jaroslav Kysela " "2008-05-19 13:19:20 +0200" -"Mark Brown " "2008-05-19 12:31:28 +0200" "Jaroslav Kysela " "2008-05-19 17:28:43 +0200" -"Mark Brown " "2008-05-19 12:32:25 +0200" "Jaroslav Kysela " "2008-05-19 17:29:24 +0200" -"Mark Brown " "2008-05-13 14:54:43 +0200" "Jaroslav Kysela " "2008-05-19 17:32:08 +0200" -"Werner Almesberger " "2008-04-14 14:26:44 +0200" "Jaroslav Kysela " "2008-05-19 17:55:10 +0200" -"Clemens Ladisch " "2008-05-13 09:26:01 +0200" "Jaroslav Kysela " "2008-05-19 13:19:17 +0200" -"Takashi Iwai " "2008-05-29 08:16:56 +0200" "Takashi Iwai " "2008-05-30 16:20:42 +0200" -"Takashi Iwai " "2008-05-30 15:32:15 +0200" "Takashi Iwai " "2008-05-30 16:22:10 +0200" -"Takashi Iwai " "2008-05-30 16:54:49 +0200" "Takashi Iwai " "2008-05-30 16:56:00 +0200" -"Takashi Iwai " "2008-06-03 14:46:34 +0200" "Takashi Iwai " "2008-06-03 14:56:53 +0200" -"Tony Vroon " "2008-06-04 12:08:30 +0200" "Takashi Iwai " "2008-06-04 12:12:35 +0200" -"Jaroslav Franek " "2008-06-06 11:04:19 +0200" "Takashi Iwai " "2008-06-06 11:16:06 +0200" -"Clemens Ladisch " "2008-06-16 14:13:52 +0200" "Takashi Iwai " "2008-06-16 15:16:11 +0200" -"eric miao " "2008-05-26 03:28:09 +0100" "Russell King " "2008-07-07 13:23:37 +0100" -"David Howells " "2008-07-08 17:36:45 +0100" "David Woodhouse " "2008-07-10 14:27:11 +0100" -"David Woodhouse " "2008-05-26 23:01:27 +0100" "David Woodhouse " "2008-07-10 14:47:44 +0100" -"David Woodhouse " "2008-05-29 14:48:34 +0300" "David Woodhouse " "2008-07-10 14:47:46 +0100" -"David Woodhouse " "2008-05-29 15:07:34 +0300" "David Woodhouse " "2008-07-10 14:47:48 +0100" -"Rene Herman " "2008-07-15 03:00:21 +0200" "Takashi Iwai " "2008-07-15 15:08:25 +0200" -"Roel Kluin " "2008-07-15 15:07:19 +0200" "Takashi Iwai " "2008-07-15 15:08:28 +0200" -"Takashi Iwai " "2008-07-15 16:28:43 +0200" "Takashi Iwai " "2008-07-16 12:03:24 +0200" -"Rene Herman " "2008-07-17 09:22:29 +0200" "Takashi Iwai " "2008-07-17 11:58:38 +0200" -"Rene Herman " "2008-07-17 14:02:16 +0200" "Takashi Iwai " "2008-07-17 14:29:55 +0200" -"Mark Brown " "2008-07-17 15:06:50 +0100" "Takashi Iwai " "2008-07-17 16:17:16 +0200" -"Mark Brown " "2008-07-17 15:06:51 +0100" "Takashi Iwai " "2008-07-17 16:17:17 +0200" -"Alexander Holler " "2008-07-17 23:36:15 +0200" "Takashi Iwai " "2008-07-17 23:43:13 +0200" -"Takashi Iwai " "2008-07-17 23:37:20 +0200" "Takashi Iwai " "2008-07-18 11:59:40 +0200" -"Rene Herman " "2008-07-18 11:15:12 +0200" "Takashi Iwai " "2008-07-18 12:01:45 +0200" -"Kailang Yang " "2008-07-18 12:36:43 +0200" "Takashi Iwai " "2008-07-18 12:39:09 +0200" -"Marek Vasut " "2008-07-20 17:36:20 +0200" "Takashi Iwai " "2008-07-20 17:39:38 +0200" -"Dmitry Baryshkov " "2008-06-14 11:42:57 +0100" "Russell King " "2008-07-07 13:22:04 +0100" -"Travis Place " "2008-07-27 10:13:26 +0200" "Takashi Iwai " "2008-07-27 10:22:26 +0200" -"Jaroslav Kysela " "2008-07-28 17:07:07 +0200" "Jaroslav Kysela " "2008-07-28 17:07:07 +0200" -"Huang Weiyi " "2008-07-26 20:43:01 +0800" "Takashi Iwai " "2008-07-29 12:27:03 +0200" -"Timur Tabi " "2008-07-28 17:04:39 -0500" "Takashi Iwai " "2008-07-29 12:27:10 +0200" -"Dmitry Baryshkov " "2008-07-29 11:42:22 +0100" "Takashi Iwai " "2008-07-29 12:57:10 +0200" -"Mark Brown " "2008-07-29 11:42:23 +0100" "Takashi Iwai " "2008-07-29 16:00:33 +0200" -"Timur Tabi " "2008-08-01 14:58:44 -0500" "Takashi Iwai " "2008-08-04 12:26:23 +0200" -"Clemens Ladisch " "2008-07-28 10:28:43 +0200" "Takashi Iwai " "2008-08-14 10:44:13 +0200" -"Clemens Ladisch " "2008-08-26 11:06:26 +0200" "Takashi Iwai " "2008-08-26 12:43:13 +0200" -"Travis Place " "2008-08-25 08:11:50 +0200" "Takashi Iwai " "2008-08-25 08:13:46 +0200" -"Stephen Rothwell " "2008-08-26 10:33:32 +1000" "Linus Torvalds " "2008-08-25 17:47:42 -0700" -"Jaroslav Kysela " "2008-08-25 08:11:50 +0200" "Jaroslav Kysela " "2008-08-29 10:01:04 +0200" -"Takashi Iwai " "2008-08-27 07:56:43 +0200" "Takashi Iwai " "2008-08-27 08:02:49 +0200" -"Clemens Ladisch " "2008-08-29 13:08:34 +0200" "Takashi Iwai " "2008-08-29 14:15:19 +0200" -"Matthew Ranostay " "2008-09-01 08:17:56 +0200" "Takashi Iwai " "2008-09-01 08:17:56 +0200" -"Dmitry Baryshkov " "2008-08-31 00:45:02 +0400" "Takashi Iwai " "2008-09-01 08:34:46 +0200" -"Takashi Iwai " "2008-09-02 14:48:20 +0200" "Takashi Iwai " "2008-09-02 17:25:33 +0200" -"Haavard Skinnemoen " "2008-09-19 18:50:45 +0200" "Takashi Iwai " "2008-09-22 12:14:28 +0200" -"Timur Tabi " "2008-07-29 16:35:52 -0500" "Takashi Iwai " "2008-09-29 12:53:18 +0200" -"Risto Suominen " "2008-08-25 08:02:12 +0200" "Takashi Iwai " "2008-10-02 12:50:04 +0200" -"Risto Suominen " "2008-08-25 08:04:23 +0200" "Takashi Iwai " "2008-10-02 12:50:37 +0200" -"David S. Miller " "2008-08-27 18:09:11 -0700" "David S. Miller " "2008-08-29 02:13:15 -0700" -"David S. Miller " "2008-08-27 00:30:59 -0700" "David S. Miller " "2008-08-29 02:14:56 -0700" -"David S. Miller " "2008-08-27 00:33:26 -0700" "David S. Miller " "2008-08-29 02:14:58 -0700" -"Russell King " "2008-09-25 13:30:07 +0100" "Russell King " "2008-09-25 13:30:07 +0100" -"Eric Miao " "2008-09-08 15:37:50 +0800" "Russell King " "2008-10-07 19:12:56 +0100" -"Frank Mandarino " "2008-09-30 10:42:40 -0400" "Takashi Iwai " "2008-10-13 02:16:05 +0200" -"Arun KS " "2008-10-13 15:47:25 +0530" "Takashi Iwai " "2008-10-13 14:52:50 +0200" -"Matthew Ranostay " "2008-10-13 13:22:45 -0400" "Takashi Iwai " "2008-10-14 07:42:55 +0200" -"Mark Brown " "2008-10-13 19:16:14 +0100" "Takashi Iwai " "2008-10-14 07:43:45 +0200" -"Marc Zyngier " "2008-10-14 09:57:05 +0100" "Takashi Iwai " "2008-10-14 11:02:21 +0200" -"Takashi Iwai " "2008-10-21 17:01:47 +0200" "Takashi Iwai " "2008-10-21 17:01:47 +0200" -"Harvey Harrison " "2008-10-21 20:28:04 -0700" "Takashi Iwai " "2008-10-22 08:00:46 +0200" -"Mark Brown " "2008-10-22 13:27:49 +0100" "Takashi Iwai " "2008-10-22 17:22:01 +0200" -"Jarkko Nikula " "2008-10-22 15:00:29 +0300" "Takashi Iwai " "2008-10-22 18:18:24 +0200" -"Arjan van de Ven " "2008-09-01 15:25:20 -0700" "Arjan van de Ven " "2008-09-05 21:35:23 -0700" -"Takashi Iwai " "2008-08-11 10:18:39 +0200" "Jaroslav Kysela " "2008-10-27 08:29:30 +0100" -"Arjan van de Ven " "2008-09-28 16:20:09 -0700" "Takashi Iwai " "2008-10-21 09:31:10 +0200" -"Bastien Nocera " "2008-10-29 12:59:05 +0000" "Takashi Iwai " "2008-10-29 15:12:00 +0100" -"Alan Cox " "2008-10-27 15:21:19 +0000" "Takashi Iwai " "2008-10-27 16:36:30 +0100" -"Takashi Iwai " "2008-11-03 10:21:36 +0100" "Takashi Iwai " "2008-11-03 10:21:36 +0100" -"Takashi Iwai " "2008-11-04 13:30:57 +0100" "Takashi Iwai " "2008-11-04 13:30:57 +0100" -"Takashi Iwai " "2008-11-05 11:30:56 +0100" "Takashi Iwai " "2008-11-05 11:30:56 +0100" -"Andrew Morton " "2008-11-06 12:05:21 -0800" "Takashi Iwai " "2008-11-07 01:31:51 +0100" -"Takashi Iwai " "2008-11-11 16:46:19 +0100" "Takashi Iwai " "2008-11-11 16:46:19 +0100" -"Takashi Iwai " "2008-11-11 16:47:24 +0100" "Takashi Iwai " "2008-11-11 18:00:53 +0100" -"Takashi Iwai " "2008-11-12 09:48:04 +0100" "Takashi Iwai " "2008-11-12 10:00:56 +0100" -"Takashi Iwai " "2008-11-12 16:45:04 +0100" "Takashi Iwai " "2008-11-13 14:37:14 +0100" -"Matthew Ranostay " "2008-11-14 17:46:22 -0500" "Takashi Iwai " "2008-11-15 19:04:26 +0100" -"Takashi Iwai " "2008-11-18 10:55:36 +0100" "Takashi Iwai " "2008-11-18 10:55:36 +0100" -"Takashi Iwai " "2008-07-30 15:01:44 +0200" "Jaroslav Kysela " "2008-11-21 15:43:16 +0100" -"Matthew Ranostay " "2008-10-25 01:06:04 -0400" "Jaroslav Kysela " "2008-11-21 15:51:53 +0100" -"Takashi Iwai " "2008-07-30 15:01:44 +0200" "Takashi Iwai " "2008-10-13 02:42:58 +0200" -"Takashi Iwai " "2008-07-30 15:01:44 +0200" "Takashi Iwai " "2008-10-13 02:42:59 +0200" -"Takashi Iwai " "2008-07-30 15:01:45 +0200" "Takashi Iwai " "2008-10-13 02:43:00 +0200" -"Takashi Iwai " "2008-07-30 15:01:45 +0200" "Takashi Iwai " "2008-10-13 02:43:01 +0200" -"Takashi Iwai " "2008-07-30 15:01:45 +0200" "Takashi Iwai " "2008-10-13 02:43:02 +0200" -"Takashi Iwai " "2008-07-30 15:01:46 +0200" "Takashi Iwai " "2008-10-13 02:43:02 +0200" -"Takashi Iwai " "2008-07-30 15:01:46 +0200" "Takashi Iwai " "2008-10-13 02:43:03 +0200" -"Takashi Iwai " "2008-07-30 15:01:46 +0200" "Takashi Iwai " "2008-10-13 02:43:04 +0200" -"Matthew Ranostay " "2008-10-15 14:45:38 -0400" "Takashi Iwai " "2008-10-16 08:43:24 +0200" -"Jean Delvare " "2008-10-15 19:57:12 +0200" "Takashi Iwai " "2008-10-16 08:50:17 +0200" -"Jean Delvare " "2008-10-15 19:58:12 +0200" "Takashi Iwai " "2008-10-16 08:50:41 +0200" -"Mark Brown " "2008-10-16 11:00:07 +0100" "Takashi Iwai " "2008-10-16 14:28:44 +0200" -"Takashi Iwai " "2008-10-16 16:17:30 +0200" "Takashi Iwai " "2008-10-16 16:17:30 +0200" -"Takashi Iwai " "2008-10-16 16:39:56 +0200" "Takashi Iwai " "2008-10-16 16:39:56 +0200" -"Takashi Iwai " "2008-08-11 10:18:39 +0200" "Takashi Iwai " "2008-10-20 14:47:15 +0200" -"Takashi Iwai " "2008-08-12 13:39:01 +0200" "Takashi Iwai " "2008-10-20 15:31:30 +0200" -"Takashi Iwai " "2008-08-11 10:18:39 +0200" "Takashi Iwai " "2008-10-20 16:02:28 +0200" -"Vedran Miletic " "2008-10-21 17:42:54 +0200" "Takashi Iwai " "2008-10-21 17:44:02 +0200" -"Vedran Miletic " "2008-10-21 21:31:27 +0200" "Takashi Iwai " "2008-10-21 21:31:27 +0200" -"Johannes Berg " "2008-10-23 15:47:56 +0200" "Takashi Iwai " "2008-10-23 18:43:42 +0200" -"Vedran Miletic " "2008-10-23 18:51:00 +0200" "Takashi Iwai " "2008-10-23 18:52:24 +0200" -"Takashi Iwai " "2008-10-24 18:16:50 +0200" "Takashi Iwai " "2008-10-24 18:16:50 +0200" -"Matthew Ranostay " "2008-10-25 01:05:29 -0400" "Takashi Iwai " "2008-10-27 08:15:14 +0100" -"Matthew Ranostay " "2008-10-25 01:05:04 -0400" "Takashi Iwai " "2008-10-27 08:15:14 +0100" -"Matthew Ranostay " "2008-10-25 01:05:45 -0400" "Takashi Iwai " "2008-10-27 08:15:15 +0100" -"Matthew Ranostay " "2008-10-25 01:06:04 -0400" "Takashi Iwai " "2008-10-27 08:15:15 +0100" -"Takashi Iwai " "2008-10-28 11:38:58 +0100" "Takashi Iwai " "2008-10-28 11:44:34 +0100" -"Takashi Iwai " "2008-10-29 08:15:30 +0100" "Takashi Iwai " "2008-10-29 08:16:22 +0100" -"Jaroslav Kysela " "2008-10-29 13:41:35 +0100" "Takashi Iwai " "2008-10-29 14:10:13 +0100" -"Takashi Iwai " "2008-10-29 16:08:01 +0100" "Takashi Iwai " "2008-10-29 16:08:01 +0100" -"Troy Kisky " "2008-10-13 17:42:14 -0700" "Mark Brown " "2008-10-30 14:34:02 +0000" -"Mark Brown " "2008-10-14 13:58:36 +0100" "Mark Brown " "2008-10-30 14:34:03 +0000" -"Mark Brown " "2008-10-21 21:45:08 +0100" "Mark Brown " "2008-10-30 14:34:03 +0000" -"Mark Brown " "2008-10-28 13:02:31 +0000" "Mark Brown " "2008-10-30 14:34:03 +0000" -"Mark Brown " "2008-07-30 19:12:04 +0100" "Mark Brown " "2008-10-30 15:45:21 +0000" -"Mark Brown " "2008-10-28 15:04:35 +0000" "Mark Brown " "2008-10-30 15:54:10 +0000" -"Mark Brown " "2008-10-22 22:41:11 +0100" "Mark Brown " "2008-10-30 15:54:10 +0000" -"Timur Tabi " "2008-08-07 11:22:32 -0500" "Mark Brown " "2008-10-30 15:54:11 +0000" -"Takashi Iwai " "2008-10-30 17:53:19 +0100" "Takashi Iwai " "2008-10-30 17:53:19 +0100" -"Stephen Rothwell " "2008-10-31 14:41:06 +1100" "Takashi Iwai " "2008-10-31 07:32:12 +0100" -"Sedji Gaouaou " "2008-10-03 16:57:50 +0200" "Mark Brown " "2008-10-31 13:12:26 +0000" -"Sedji Gaouaou " "2008-10-03 16:58:58 +0200" "Mark Brown " "2008-10-31 13:13:20 +0000" -"Steve Sakoman " "2008-10-30 21:35:26 -0700" "Mark Brown " "2008-10-31 12:33:27 +0000" -"Steve Sakoman " "2008-10-30 21:50:13 -0700" "Mark Brown " "2008-10-31 12:33:38 +0000" -"Steve Sakoman " "2008-10-30 21:55:24 -0700" "Mark Brown " "2008-10-31 12:33:43 +0000" -"Takashi Iwai " "2008-10-31 15:01:37 +0100" "Takashi Iwai " "2008-10-31 17:24:21 +0100" -"Takashi Iwai " "2008-10-31 15:24:04 +0100" "Takashi Iwai " "2008-10-31 17:24:30 +0100" -"Takashi Iwai " "2008-10-31 16:37:07 +0100" "Takashi Iwai " "2008-10-31 17:24:39 +0100" -"Takashi Iwai " "2008-10-31 17:48:56 +0100" "Takashi Iwai " "2008-10-31 17:48:56 +0100" -"Takashi Iwai " "2008-11-01 11:01:50 +0100" "Takashi Iwai " "2008-11-01 11:03:52 +0100" -"Takashi Iwai " "2008-11-03 08:17:05 +0100" "Takashi Iwai " "2008-11-03 08:57:12 +0100" -"Zoltan Devai " "2008-11-03 00:30:28 +0100" "Takashi Iwai " "2008-11-03 08:57:25 +0100" -"Kay Sievers " "2008-11-02 03:50:35 +0100" "Takashi Iwai " "2008-11-03 08:57:33 +0100" -"Takashi Iwai " "2008-11-03 08:51:33 +0100" "Takashi Iwai " "2008-11-03 08:57:40 +0100" -"Takashi Iwai " "2008-11-03 10:07:43 +0100" "Takashi Iwai " "2008-11-03 10:07:43 +0100" -"Matthew Ranostay " "2008-11-03 08:12:43 -0500" "Takashi Iwai " "2008-11-03 14:29:47 +0100" -"Takashi Iwai " "2008-11-03 17:47:49 +0100" "Takashi Iwai " "2008-11-03 17:50:48 +0100" -"Troy Kisky " "2008-11-03 12:22:07 -0700" "Takashi Iwai " "2008-11-04 08:40:55 +0100" -"Takashi Iwai " "2008-11-04 08:43:08 +0100" "Takashi Iwai " "2008-11-04 08:43:08 +0100" -"Takashi Iwai " "2008-11-03 17:39:46 +0100" "Takashi Iwai " "2008-11-03 17:39:46 +0100" -"Takashi Iwai " "2008-11-04 17:48:39 +0100" "Takashi Iwai " "2008-11-04 17:48:39 +0100" -"Takashi Iwai " "2008-11-04 18:06:23 +0100" "Takashi Iwai " "2008-11-04 18:06:23 +0100" -"Wu, Fengguang " "2008-11-05 11:16:56 +0800" "Takashi Iwai " "2008-11-05 07:54:03 +0100" -"Takashi Iwai " "2008-11-05 08:06:08 +0100" "Takashi Iwai " "2008-11-05 08:09:10 +0100" -"Takashi Iwai " "2008-11-05 14:57:20 +0100" "Takashi Iwai " "2008-11-05 14:57:20 +0100" -"Takashi Iwai " "2008-11-05 17:41:23 +0100" "Takashi Iwai " "2008-11-05 17:41:23 +0100" -"Takashi Iwai " "2008-11-06 16:50:40 +0100" "Takashi Iwai " "2008-11-06 16:50:40 +0100" -"Takashi Iwai " "2008-11-06 17:11:10 +0100" "Takashi Iwai " "2008-11-06 17:29:48 +0100" -"Tony Vroon " "2008-11-06 15:08:49 +0000" "Takashi Iwai " "2008-11-06 17:32:34 +0100" -"Takashi Iwai " "2008-11-07 00:23:30 +0100" "Takashi Iwai " "2008-11-07 00:23:30 +0100" -"Takashi Iwai " "2008-11-07 00:49:48 +0100" "Takashi Iwai " "2008-11-07 00:51:36 +0100" -"Takashi Iwai " "2008-11-07 09:08:15 +0100" "Takashi Iwai " "2008-11-07 09:08:15 +0100" -"Takashi Iwai " "2008-11-07 09:37:22 +0100" "Takashi Iwai " "2008-11-07 09:37:22 +0100" -"Takashi Iwai " "2008-11-07 14:49:28 +0100" "Takashi Iwai " "2008-11-07 14:51:15 +0100" -"Takashi Iwai " "2008-11-07 14:53:09 +0100" "Takashi Iwai " "2008-11-07 14:53:09 +0100" -"Michel Marti " "2008-11-08 11:33:32 +0100" "Takashi Iwai " "2008-11-09 12:47:12 +0100" -"Tim Blechmann " "2008-11-09 12:50:52 +0100" "Takashi Iwai " "2008-11-09 12:50:52 +0100" -"Tim Blechmann " "2008-11-08 14:42:18 +0100" "Takashi Iwai " "2008-11-09 12:55:18 +0100" -"Takashi Iwai " "2008-10-30 15:57:05 +0100" "Liam Girdwood " "2008-11-09 14:49:23 +0000" -"Ville Syrjala " "2008-11-09 20:32:40 +0200" "Takashi Iwai " "2008-11-10 07:54:25 +0100" -"Huang Weiyi " "2008-10-31 22:50:00 +0800" "Takashi Iwai " "2008-11-04 18:03:21 +0100" -"Takashi Iwai " "2008-11-10 16:24:26 +0100" "Takashi Iwai " "2008-11-10 16:24:26 +0100" -"Travis Place " "2008-11-10 17:56:23 +0100" "Takashi Iwai " "2008-11-10 17:57:14 +0100" -"Takashi Iwai " "2008-11-12 10:02:04 +0100" "Takashi Iwai " "2008-11-12 10:02:04 +0100" -"Jaroslav Kysela " "2008-11-12 11:02:25 +0100" "Takashi Iwai " "2008-11-12 11:13:29 +0100" -"Takashi Iwai " "2008-11-12 15:18:41 +0100" "Takashi Iwai " "2008-11-12 15:18:41 +0100" -"Jaroslav Kysela " "2008-11-12 16:31:37 +0100" "Takashi Iwai " "2008-11-12 17:07:37 +0100" -"Jaroslav Kysela " "2008-11-12 16:37:48 +0100" "Takashi Iwai " "2008-11-12 17:07:46 +0100" -"Jaroslav Kysela " "2008-11-12 16:53:47 +0100" "Takashi Iwai " "2008-11-12 17:07:52 +0100" -"Wu Fengguang " "2008-11-13 10:19:38 +0800" "Takashi Iwai " "2008-11-13 07:55:40 +0100" -"Yang, Libin " "2008-11-13 11:07:07 +0100" "Takashi Iwai " "2008-11-13 11:07:07 +0100" -"Takashi Iwai " "2008-11-13 13:08:56 +0100" "Takashi Iwai " "2008-11-13 14:37:16 +0100" -"Takashi Iwai " "2008-11-14 13:58:43 +0100" "Takashi Iwai " "2008-11-14 13:58:43 +0100" -"Takashi Iwai " "2008-11-14 14:03:33 +0100" "Takashi Iwai " "2008-11-14 14:03:33 +0100" -"Mark Brown " "2008-11-14 14:40:46 +0000" "Mark Brown " "2008-11-14 14:40:46 +0000" -"Mark Brown " "2008-11-13 14:33:14 +0000" "Mark Brown " "2008-11-14 14:44:53 +0000" -"Takashi Iwai " "2008-11-15 19:05:21 +0100" "Takashi Iwai " "2008-11-15 19:05:21 +0100" -"Julia Lawall " "2008-11-14 19:08:18 +0100" "Takashi Iwai " "2008-11-15 19:07:29 +0100" -"Takashi Iwai " "2008-11-15 19:28:54 +0100" "Takashi Iwai " "2008-11-15 19:28:54 +0100" -"Wu Fengguang " "2008-11-17 09:51:09 +0100" "Takashi Iwai " "2008-11-17 09:51:09 +0100" -"Matthew Ranostay " "2008-11-16 11:42:34 -0500" "Takashi Iwai " "2008-11-17 09:56:35 +0100" -"Wu Fengguang " "2008-11-17 16:57:33 +0800" "Takashi Iwai " "2008-11-17 10:03:41 +0100" -"Risto Suominen " "2008-11-18 07:35:14 +0100" "Takashi Iwai " "2008-11-18 07:38:00 +0100" -"Wu Fengguang " "2008-11-18 10:21:55 +0800" "Takashi Iwai " "2008-11-18 07:38:28 +0100" -"Wu Fengguang " "2008-11-18 11:47:51 +0800" "Takashi Iwai " "2008-11-18 07:38:51 +0100" -"Wu Fengguang " "2008-11-18 11:47:52 +0800" "Takashi Iwai " "2008-11-18 07:39:03 +0100" -"Wu Fengguang " "2008-11-18 11:47:53 +0800" "Takashi Iwai " "2008-11-18 07:39:12 +0100" -"Takashi Iwai " "2008-11-18 09:32:42 +0100" "Takashi Iwai " "2008-11-18 09:43:05 +0100" -"Takashi Iwai " "2008-11-18 09:36:55 +0100" "Takashi Iwai " "2008-11-18 09:43:10 +0100" -"Takashi Iwai " "2008-11-18 10:38:56 +0100" "Takashi Iwai " "2008-11-18 10:42:00 +0100" -"Takashi Iwai " "2008-11-18 10:45:15 +0100" "Takashi Iwai " "2008-11-18 10:45:15 +0100" -"Takashi Iwai " "2008-11-18 10:48:41 +0100" "Takashi Iwai " "2008-11-18 10:48:41 +0100" -"Takashi Iwai " "2008-11-05 07:58:25 +0100" "Takashi Iwai " "2008-11-05 07:58:25 +0100" -"Takashi Iwai " "2008-11-18 12:36:33 +0100" "Takashi Iwai " "2008-11-18 12:36:33 +0100" -"Naresh Medisetty " "2008-11-18 11:01:03 +0530" "Mark Brown " "2008-11-18 11:40:04 +0000" -"Mike Frysinger " "2008-11-18 16:18:15 +0800" "Mark Brown " "2008-11-18 11:40:18 +0000" -"Cliff Cai " "2008-11-18 16:18:16 +0800" "Mark Brown " "2008-11-18 11:40:18 +0000" -"Cliff Cai " "2008-11-18 16:18:17 +0800" "Mark Brown " "2008-11-18 11:40:19 +0000" -"Cliff Cai " "2008-11-18 16:18:18 +0800" "Mark Brown " "2008-11-18 11:40:21 +0000" -"Michael Hennerich " "2008-11-18 16:18:19 +0800" "Mark Brown " "2008-11-18 12:32:11 +0000" -"Mike Frysinger " "2008-11-18 16:18:20 +0800" "Mark Brown " "2008-11-18 12:32:32 +0000" -"Bryan Wu " "2008-11-18 16:18:21 +0800" "Mark Brown " "2008-11-18 12:32:32 +0000" -"Mike Frysinger " "2008-11-18 16:18:22 +0800" "Mark Brown " "2008-11-18 12:32:33 +0000" -"Mark Brown " "2008-11-18 12:25:46 +0000" "Mark Brown " "2008-11-18 12:32:33 +0000" -"Hannes Eder " "2008-11-18 12:25:06 -0500" "Takashi Iwai " "2008-11-18 18:27:58 +0100" -"Wu Fengguang " "2008-11-19 08:56:15 +0800" "Takashi Iwai " "2008-11-19 07:35:21 +0100" -"Wu Fengguang " "2008-11-19 08:56:16 +0800" "Takashi Iwai " "2008-11-19 07:35:28 +0100" -"Wu Fengguang " "2008-11-19 08:56:17 +0800" "Takashi Iwai " "2008-11-19 07:35:36 +0100" -"Wu Fengguang " "2008-11-19 08:56:18 +0800" "Takashi Iwai " "2008-11-19 07:35:44 +0100" -"Matthew Ranostay " "2008-11-18 20:54:17 -0500" "Takashi Iwai " "2008-11-19 07:37:23 +0100" -"Wu Fengguang " "2008-11-19 15:13:59 +0800" "Takashi Iwai " "2008-11-19 09:41:59 +0100" -"Wu Fengguang " "2008-11-19 15:14:00 +0800" "Takashi Iwai " "2008-11-19 09:42:07 +0100" -"Wu Fengguang " "2008-11-19 15:14:01 +0800" "Takashi Iwai " "2008-11-19 09:42:21 +0100" -"Wu Fengguang " "2008-11-19 15:14:02 +0800" "Takashi Iwai " "2008-11-19 09:42:30 +0100" -"Wu Fengguang " "2008-11-19 15:14:03 +0800" "Takashi Iwai " "2008-11-19 09:42:38 +0100" -"Takashi Iwai " "2008-11-19 14:14:50 +0100" "Takashi Iwai " "2008-11-19 14:14:50 +0100" -"Hugo Villeneuve " "2008-11-19 01:37:31 -0500" "Mark Brown " "2008-11-19 13:16:38 +0000" -"Hugo Villeneuve " "2008-11-19 01:37:32 -0500" "Mark Brown " "2008-11-19 13:18:42 +0000" -"Arun KS " "2008-11-19 17:45:19 +0530" "Mark Brown " "2008-11-19 13:18:59 +0000" -"Mark Brown " "2008-11-18 21:57:17 +0000" "Mark Brown " "2008-11-19 13:24:52 +0000" -"Mark Brown " "2008-11-18 22:17:49 +0000" "Mark Brown " "2008-11-19 13:25:32 +0000" -"Wu Fengguang " "2008-11-20 09:24:52 +0800" "Takashi Iwai " "2008-11-20 08:17:15 +0100" -"Vincent Petry " "2008-11-18 22:21:57 +0800" "Takashi Iwai " "2008-11-20 08:22:24 +0100" -"Matthew Ranostay " "2008-11-16 11:42:34 -0500" "Takashi Iwai " "2008-11-20 17:11:10 +0100" -"Takashi Iwai " "2008-11-21 02:25:48 +0100" "Takashi Iwai " "2008-11-21 02:25:48 +0100" -"Hannes Eder " "2008-11-20 21:25:25 +0100" "Takashi Iwai " "2008-11-21 08:13:15 +0100" -"Matthew Ranostay " "2008-11-20 21:21:43 -0500" "Takashi Iwai " "2008-11-21 08:17:00 +0100" -"Wu Fengguang " "2008-11-21 09:42:59 +0800" "Takashi Iwai " "2008-11-21 08:27:30 +0100" -"Wu Fengguang " "2008-11-21 12:34:05 +0800" "Takashi Iwai " "2008-11-21 08:27:44 +0100" -"Wu Fengguang " "2008-11-21 11:41:50 +0800" "Takashi Iwai " "2008-11-21 08:27:49 +0100" -"Takashi Iwai " "2008-11-21 08:37:03 +0100" "Takashi Iwai " "2008-11-21 08:37:03 +0100" -"Takashi Iwai " "2008-11-21 08:54:54 +0100" "Takashi Iwai " "2008-11-21 08:54:54 +0100" -"Takashi Iwai " "2008-11-21 09:08:06 +0100" "Takashi Iwai " "2008-11-21 09:08:06 +0100" -"Takashi Iwai " "2008-11-21 09:11:50 +0100" "Takashi Iwai " "2008-11-21 09:17:30 +0100" -"Takashi Iwai " "2008-11-21 09:26:20 +0100" "Takashi Iwai " "2008-11-21 09:26:20 +0100" -"Takashi Iwai " "2008-11-21 09:32:40 +0100" "Takashi Iwai " "2008-11-21 09:32:40 +0100" -"Hannes Eder " "2008-11-21 16:03:24 +0100" "Takashi Iwai " "2008-11-21 16:05:16 +0100" -"Takashi Iwai " "2008-11-21 18:01:44 +0100" "Takashi Iwai " "2008-11-21 18:01:44 +0100" -"Takashi Iwai " "2008-11-21 21:24:03 +0100" "Takashi Iwai " "2008-11-21 21:24:03 +0100" -"Wu Fengguang " "2008-11-22 09:40:51 +0800" "Takashi Iwai " "2008-11-22 11:14:18 +0100" -"Wu Fengguang " "2008-11-22 09:40:52 +0800" "Takashi Iwai " "2008-11-22 11:14:32 +0100" -"Wu Fengguang " "2008-11-22 09:40:53 +0800" "Takashi Iwai " "2008-11-22 11:14:48 +0100" -"Wu Fengguang " "2008-11-22 09:40:54 +0800" "Takashi Iwai " "2008-11-22 11:15:21 +0100" -"Wu Fengguang " "2008-11-22 09:40:55 +0800" "Takashi Iwai " "2008-11-22 11:15:45 +0100" -"Wu Fengguang " "2008-11-22 09:40:56 +0800" "Takashi Iwai " "2008-11-22 11:16:04 +0100" -"Wu Fengguang " "2008-11-22 09:40:57 +0800" "Takashi Iwai " "2008-11-22 11:16:15 +0100" -"Takashi Iwai " "2008-11-24 07:51:11 +0100" "Takashi Iwai " "2008-11-24 07:51:11 +0100" -"Vincent Petry " "2008-11-23 11:31:41 +0800" "Takashi Iwai " "2008-11-24 08:10:07 +0100" -"Takashi Iwai " "2008-11-24 17:29:28 +0100" "Takashi Iwai " "2008-11-24 17:29:28 +0100" -"Marek Vasut " "2008-11-03 12:02:12 +0000" "Mark Brown " "2008-11-05 22:11:16 +0000" -"Takashi Iwai " "2008-11-25 08:17:20 +0100" "Takashi Iwai " "2008-11-25 10:31:44 +0100" -"Takashi Iwai " "2008-11-25 11:42:54 +0100" "Takashi Iwai " "2008-11-25 11:42:54 +0100" -"Takashi Iwai " "2008-11-25 08:21:51 +0100" "Takashi Iwai " "2008-11-25 11:53:50 +0100" -"Mark Brown " "2008-11-05 11:13:21 +0000" "Mark Brown " "2008-11-05 22:11:29 +0000" -"Grazvydas Ignotas " "2008-11-05 23:51:05 +0200" "Mark Brown " "2008-11-06 11:27:30 +0000" -"Takashi Iwai " "2008-11-07 00:26:52 +0100" "Takashi Iwai " "2008-11-07 00:26:52 +0100" -"Troy Kisky " "2008-11-05 18:53:28 +0000" "Mark Brown " "2008-11-07 13:27:47 +0000" -"Christian Pellegrin " "2008-11-08 08:44:16 +0100" "Mark Brown " "2008-11-10 11:40:57 +0000" -"Hugo Villeneuve " "2008-11-08 13:26:09 -0500" "Mark Brown " "2008-11-10 11:41:18 +0000" -"Naresh Medisetty " "2008-11-12 10:26:31 +0530" "Mark Brown " "2008-11-12 11:50:29 +0000" -"Jaroslav Kysela " "2008-11-11 16:51:02 +0100" "Takashi Iwai " "2008-11-12 15:55:44 +0100" -"Jarkko Nikula " "2008-11-12 17:05:41 +0200" "Mark Brown " "2008-11-13 10:31:22 +0000" -"Jarkko Nikula " "2008-11-12 17:05:51 +0200" "Mark Brown " "2008-11-13 10:31:44 +0000" -"Peter Ujfalusi " "2008-11-14 08:57:28 +0200" "Mark Brown " "2008-11-17 11:02:21 +0000" -"Christian Pellegrin " "2008-11-15 08:58:16 +0100" "Mark Brown " "2008-11-17 11:45:39 +0000" -"Christian Pellegrin " "2008-11-15 08:58:32 +0100" "Mark Brown " "2008-11-17 11:45:53 +0000" -"Mark Brown " "2008-11-17 16:59:24 +0000" "Mark Brown " "2008-11-17 17:24:50 +0000" -"Mark Brown " "2008-11-17 17:09:34 +0000" "Mark Brown " "2008-11-17 17:24:54 +0000" -"Mark Brown " "2008-11-17 17:11:14 +0000" "Mark Brown " "2008-11-17 17:26:51 +0000" -"Mark Brown " "2008-11-17 21:42:01 +0000" "Mark Brown " "2008-11-17 21:46:24 +0000" -"Mark Brown " "2008-11-18 20:40:36 +0000" "Mark Brown " "2008-11-18 20:40:36 +0000" -"Mark Brown " "2008-11-18 20:50:34 +0000" "Mark Brown " "2008-11-21 14:02:01 +0000" -"Mark Brown " "2008-11-19 19:16:05 +0000" "Mark Brown " "2008-11-21 14:02:06 +0000" -"Karl Beldan " "2008-11-20 15:39:27 +0100" "Mark Brown " "2008-11-21 14:02:07 +0000" -"Karl Beldan " "2008-11-20 15:39:31 +0100" "Mark Brown " "2008-11-21 14:02:07 +0000" -"Mark Brown " "2008-07-23 14:03:07 +0100" "Mark Brown " "2008-11-21 14:02:08 +0000" -"Mark Brown " "2008-11-18 22:11:38 +0000" "Mark Brown " "2008-11-21 14:12:10 +0000" -"Mark Brown " "2008-11-21 14:01:41 +0000" "Mark Brown " "2008-11-21 14:35:02 +0000" -"Jarkko Nikula " "2008-11-21 14:31:33 +0200" "Mark Brown " "2008-11-21 14:35:06 +0000" -"Mark Brown " "2008-11-21 14:05:48 +0000" "Mark Brown " "2008-11-21 14:35:07 +0000" -"Mark Brown " "2008-11-21 14:28:49 +0000" "Mark Brown " "2008-11-21 14:35:07 +0000" -"Mark Brown " "2008-11-21 15:08:23 +0000" "Takashi Iwai " "2008-11-21 16:18:26 +0100" -"Mark Brown " "2008-11-24 14:05:29 +0000" "Mark Brown " "2008-11-24 14:05:34 +0000" -"Peter Ujfalusi " "2008-11-24 08:25:45 +0200" "Mark Brown " "2008-11-24 14:05:39 +0000" -"Peter Ujfalusi " "2008-11-24 13:49:35 +0200" "Mark Brown " "2008-11-24 14:05:39 +0000" -"Peter Ujfalusi " "2008-11-24 13:49:36 +0200" "Mark Brown " "2008-11-24 14:05:40 +0000" -"Mark Brown " "2008-11-24 18:01:05 +0000" "Mark Brown " "2008-11-24 18:01:31 +0000" -"Mark Brown " "2008-11-24 17:45:26 +0000" "Mark Brown " "2008-11-24 18:01:37 +0000" -"Mark Brown " "2008-11-24 18:08:18 +0000" "Mark Brown " "2008-11-24 18:09:05 +0000" -"Takashi Iwai " "2008-11-25 11:58:19 +0100" "Takashi Iwai " "2008-11-25 11:58:19 +0100" -"Markus Bollinger " "2008-11-25 12:21:05 +0100" "Takashi Iwai " "2008-11-25 12:26:46 +0100" -"Markus Bollinger " "2008-11-25 12:24:54 +0100" "Takashi Iwai " "2008-11-25 12:27:03 +0100" -"Markus Bollinger " "2008-11-25 12:28:06 +0100" "Takashi Iwai " "2008-11-25 12:28:06 +0100" -"Markus Bollinger " "2008-11-25 12:37:52 +0100" "Takashi Iwai " "2008-11-25 12:53:24 +0100" -"Takashi Iwai " "2008-11-25 15:03:38 +0100" "Takashi Iwai " "2008-11-25 15:03:38 +0100" -"Takashi Iwai " "2008-11-24 07:51:11 +0100" "Takashi Iwai " "2008-11-25 15:15:05 +0100" -"Takashi Iwai " "2008-11-21 18:01:44 +0100" "Takashi Iwai " "2008-11-25 15:17:08 +0100" -"Takashi Iwai " "2008-11-25 15:18:29 +0100" "Takashi Iwai " "2008-11-25 15:18:29 +0100" -"Peter Zijlstra " "2008-11-25 12:43:51 +0100" "Ingo Molnar " "2008-11-25 15:45:46 +0100" -"Takashi Iwai " "2008-11-25 16:07:01 +0100" "Takashi Iwai " "2008-11-25 16:07:01 +0100" -"Jarkko Nikula " "2008-11-25 12:45:08 +0200" "Mark Brown " "2008-11-25 15:20:55 +0000" -"Jarkko Nikula " "2008-11-25 12:45:09 +0200" "Mark Brown " "2008-11-25 15:21:26 +0000" -"Arun KS " "2008-11-25 09:56:12 +0530" "Mark Brown " "2008-11-25 15:28:47 +0000" -"Misael Lopez Cruz " "2008-11-24 22:21:23 -0600" "Mark Brown " "2008-11-25 15:28:57 +0000" -"Dmitry Baryshkov " "2008-11-25 09:35:21 +0300" "Mark Brown " "2008-11-25 15:37:37 +0000" -"Clemens Ladisch " "2008-11-26 10:37:23 +0100" "Takashi Iwai " "2008-11-28 14:49:54 +0100" -"Andres Salomon " "2008-11-05 17:29:53 -0500" "Takashi Iwai " "2008-12-10 17:14:36 +0100" -"Jaya Kumar " "2008-11-05 17:30:08 -0500" "Takashi Iwai " "2008-12-10 17:14:37 +0100" -"Andres Salomon " "2008-11-05 17:30:30 -0500" "Takashi Iwai " "2008-12-10 17:14:38 +0100" -"Jaya Kumar " "2008-11-06 16:43:34 -0500" "Takashi Iwai " "2008-12-10 17:14:39 +0100" -"Jordan Crouse " "2008-11-06 16:43:53 -0500" "Takashi Iwai " "2008-12-10 17:14:39 +0100" -"Andres Salomon " "2008-11-06 16:44:08 -0500" "Takashi Iwai " "2008-12-10 17:14:40 +0100" -"Andres Salomon " "2008-11-06 16:46:31 -0500" "Takashi Iwai " "2008-12-10 17:14:41 +0100" -"Andres Salomon " "2008-11-06 16:47:05 -0500" "Takashi Iwai " "2008-12-10 17:14:42 +0100" -"Andres Salomon " "2008-11-06 16:49:38 -0500" "Takashi Iwai " "2008-12-10 17:14:42 +0100" -"Andres Salomon " "2008-11-06 16:49:46 -0500" "Takashi Iwai " "2008-12-10 17:14:43 +0100" -"Andres Salomon " "2008-11-06 16:49:55 -0500" "Takashi Iwai " "2008-12-10 17:14:44 +0100" -"Chris Ball " "2008-11-06 16:50:09 -0500" "Takashi Iwai " "2008-12-10 17:14:45 +0100" -"Andres Salomon " "2008-11-06 16:53:03 -0500" "Takashi Iwai " "2008-12-10 17:14:45 +0100" -"Andres Salomon " "2008-11-06 16:53:11 -0500" "Takashi Iwai " "2008-12-10 17:14:46 +0100" -"Andres Salomon " "2008-11-06 16:53:19 -0500" "Takashi Iwai " "2008-12-10 17:14:47 +0100" -"Andres Salomon " "2008-11-06 16:53:26 -0500" "Takashi Iwai " "2008-12-10 17:14:48 +0100" -"Andres Salomon " "2008-11-06 16:53:34 -0500" "Takashi Iwai " "2008-12-10 17:14:48 +0100" -"Takashi Iwai " "2008-12-18 12:17:55 +0100" "Takashi Iwai " "2008-12-18 12:17:55 +0100" -"Takashi Iwai " "2008-12-17 14:51:01 +0100" "Takashi Iwai " "2008-12-19 08:22:26 +0100" -"Peter Ujfalusi " "2008-12-31 10:08:37 +0200" "Mark Brown " "2008-12-31 13:11:59 +0000" -"Peter Ujfalusi " "2008-12-31 10:08:38 +0200" "Mark Brown " "2008-12-31 13:11:59 +0000" -"Julia Lawall " "2008-12-29 11:23:02 +0100" "Takashi Iwai " "2009-01-01 10:27:33 +0100" -"Wu Fengguang " "2008-12-26 12:20:43 +0800" "Takashi Iwai " "2009-01-01 10:28:59 +0100" -"Chris Bagwell " "2009-01-01 10:32:08 +0100" "Takashi Iwai " "2009-01-01 10:32:08 +0100" -"Stephen Ware " "2008-12-31 14:39:23 -0800" "Mark Brown " "2009-01-01 11:52:48 +0000" -"Mark Brown " "2009-01-01 12:18:17 +0000" "Mark Brown " "2009-01-01 12:18:17 +0000" -"Julia Lawall " "2009-01-01 18:14:35 +0100" "Takashi Iwai " "2009-01-02 11:52:45 +0100" -"Ulrich Dangel " "2009-01-02 19:30:13 +0100" "Takashi Iwai " "2009-01-03 11:25:44 +0100" -"Ulrich Dangel " "2009-01-02 19:30:14 +0100" "Takashi Iwai " "2009-01-03 11:26:05 +0100" -"Julia Lawall " "2009-01-03 17:54:53 +0100" "Takashi Iwai " "2009-01-04 12:10:04 +0100" -"Takashi Iwai " "2009-01-15 17:31:00 +0100" "Takashi Iwai " "2009-01-15 17:33:47 +0100" -"Luke Yelavich " "2009-01-16 15:08:02 +1100" "Takashi Iwai " "2009-01-16 10:29:37 +0100" -"Ben Nizette " "2009-01-16 08:45:45 +1100" "Mark Brown " "2009-01-16 16:39:13 +0000" -"Matthew Ranostay " "2009-01-17 18:47:27 -0500" "Takashi Iwai " "2009-01-18 11:03:51 +0100" -"Clemens Ladisch " "2009-01-19 10:07:21 +0100" "Takashi Iwai " "2009-01-19 14:07:21 +0100" -"Clemens Ladisch " "2009-01-19 10:07:58 +0100" "Takashi Iwai " "2009-01-19 14:07:36 +0100" -"Clemens Ladisch " "2009-01-19 10:08:38 +0100" "Takashi Iwai " "2009-01-19 14:07:37 +0100" -"Clemens Ladisch " "2009-01-26 08:08:34 +0100" "Jaroslav Kysela " "2009-01-29 16:23:47 +0100" -"Clemens Ladisch " "2009-01-26 08:09:28 +0100" "Jaroslav Kysela " "2009-01-29 16:23:48 +0100" -"Clemens Ladisch " "2009-01-26 08:10:19 +0100" "Jaroslav Kysela " "2009-01-29 16:23:49 +0100" -"Takashi Iwai " "2009-01-30 15:49:58 +0100" "Takashi Iwai " "2009-01-30 15:49:58 +0100" -"Roel Kluin " "2009-01-31 12:17:28 +0100" "Takashi Iwai " "2009-01-31 17:56:48 +0100" -"Mark Eggleston " "2009-01-31 17:57:54 +0100" "Takashi Iwai " "2009-01-31 17:57:54 +0100" -"Takashi Iwai " "2009-02-02 11:37:03 +0100" "Takashi Iwai " "2009-02-02 11:42:08 +0100" -"Clemens Ladisch " "2009-02-06 08:13:07 +0100" "Takashi Iwai " "2009-02-06 09:47:12 +0100" -"Eero Nurkkala " "2009-02-06 12:01:04 +0200" "Mark Brown " "2009-02-06 11:39:28 +0000" -"Jarkko Nikula " "2009-02-06 12:01:05 +0200" "Mark Brown " "2009-02-06 11:39:28 +0000" -"Mackenzie Morgan " "2009-02-10 17:13:43 +0100" "Takashi Iwai " "2009-02-10 17:13:43 +0100" -"Lopez Cruz, Misael " "2009-02-10 02:05:07 -0600" "Mark Brown " "2009-02-10 21:36:27 +0000" -"Wu Fengguang " "2009-02-11 15:22:28 +0800" "Takashi Iwai " "2009-02-11 09:08:47 +0100" -"Wu Fengguang " "2009-02-11 15:22:29 +0800" "Takashi Iwai " "2009-02-11 09:08:59 +0100" -"Wu Fengguang " "2009-02-11 15:22:30 +0800" "Takashi Iwai " "2009-02-11 09:09:07 +0100" -"Wu Fengguang " "2009-02-11 15:22:31 +0800" "Takashi Iwai " "2009-02-11 09:09:15 +0100" -"Takashi Iwai " "2009-02-12 00:06:42 +0100" "Takashi Iwai " "2009-02-12 00:06:42 +0100" -"Takashi Iwai " "2009-02-12 00:13:19 +0100" "Takashi Iwai " "2009-02-12 00:13:19 +0100" -"Clemens Ladisch " "2009-02-16 15:22:39 +0100" "Takashi Iwai " "2009-02-16 15:31:48 +0100" -"Clemens Ladisch " "2009-02-17 09:50:30 +0100" "Takashi Iwai " "2009-02-19 10:15:39 +0100" -"Juan Jesus Garcia de Soria " "2009-02-23 08:11:59 +0100" "Takashi Iwai " "2009-02-23 08:13:53 +0100" -"Takashi Iwai " "2009-02-27 17:36:33 +0100" "Takashi Iwai " "2009-02-27 17:36:33 +0100" -"Takashi Iwai " "2009-02-27 17:44:07 +0100" "Takashi Iwai " "2009-02-27 17:44:07 +0100" -"Aristeu Sergio Rozanski Filho " "2009-02-12 17:50:37 -0500" "Jaroslav Kysela " "2009-03-05 09:28:13 +0100" -"Takashi Iwai " "2009-02-13 09:31:20 +0100" "Jaroslav Kysela " "2009-03-05 09:28:15 +0100" -"Herton Ronaldo Krzesinski " "2009-02-16 10:23:00 +0100" "Jaroslav Kysela " "2009-03-05 09:28:21 +0100" -"Takashi Iwai " "2009-02-16 14:16:36 +0100" "Jaroslav Kysela " "2009-03-05 09:28:24 +0100" -"Krzysztof Helt " "2009-03-16 21:32:25 +0100" "Takashi Iwai " "2009-03-17 09:27:47 +0100" -"Takashi Iwai " "2009-03-17 07:47:18 +0100" "Takashi Iwai " "2009-03-18 07:45:41 +0100" -"Takashi Iwai " "2009-03-17 07:49:14 +0100" "Takashi Iwai " "2009-03-18 07:46:21 +0100" -"Viral Mehta " "2009-03-10 15:43:18 +0100" "Takashi Iwai " "2009-03-18 07:52:28 +0100" -"Jiri Slaby " "2009-03-11 20:11:40 +0100" "Takashi Iwai " "2009-03-18 08:03:33 +0100" -"Jiri Slaby " "2009-03-11 20:11:41 +0100" "Takashi Iwai " "2009-03-18 08:03:49 +0100" -"Takashi Iwai " "2009-03-17 14:00:06 +0100" "Takashi Iwai " "2009-03-18 08:04:01 +0100" -"Ian Molton " "2009-01-06 20:11:51 +0000" "Ian Molton " "2009-01-07 21:32:54 +0000" -"Andrea Borgia " "2009-01-07 22:58:50 +0100" "Takashi Iwai " "2009-01-07 23:32:04 +0100" -"Mark Brown " "2009-01-07 18:25:13 +0000" "Mark Brown " "2009-01-09 10:31:30 +0000" -"Mark Brown " "2009-01-07 17:31:10 +0000" "Mark Brown " "2009-01-09 10:31:31 +0000" -"Ian Molton " "2009-01-09 00:23:21 +0000" "Mark Brown " "2009-01-09 10:39:49 +0000" -"Krzysztof Helt " "2009-01-09 23:10:52 +0100" "Takashi Iwai " "2009-01-11 13:09:05 +0100" -"Takashi Iwai " "2008-12-28 16:43:35 +0100" "Takashi Iwai " "2009-01-12 15:20:26 +0100" -"Takashi Iwai " "2008-12-28 16:44:30 +0100" "Takashi Iwai " "2009-01-12 15:20:55 +0100" -"Takashi Iwai " "2008-12-28 16:45:02 +0100" "Takashi Iwai " "2009-01-12 15:21:19 +0100" -"Takashi Iwai " "2008-12-28 16:45:34 +0100" "Takashi Iwai " "2009-01-12 15:21:53 +0100" -"Takashi Iwai " "2008-12-28 16:47:30 +0100" "Takashi Iwai " "2009-01-12 15:21:54 +0100" -"Takashi Iwai " "2008-12-28 16:55:08 +0100" "Takashi Iwai " "2009-01-12 15:21:55 +0100" -"Takashi Iwai " "2008-12-28 16:59:41 +0100" "Takashi Iwai " "2009-01-12 15:21:56 +0100" -"Takashi Iwai " "2008-12-28 17:03:56 +0100" "Takashi Iwai " "2009-01-12 15:21:56 +0100" -"Krzysztof Helt " "2009-01-12 21:25:04 +0100" "Takashi Iwai " "2009-01-13 07:52:24 +0100" -"Andrea Borgia " "2009-01-12 23:17:47 +0100" "Takashi Iwai " "2009-01-13 07:54:57 +0100" -"Takashi Iwai " "2009-01-14 09:34:06 +0100" "Takashi Iwai " "2009-01-14 09:34:06 +0100" -"Takashi Iwai " "2009-01-15 17:05:24 +0100" "Takashi Iwai " "2009-01-15 17:58:18 +0100" -"Johannes Berg " "2009-01-15 18:21:48 +0100" "Takashi Iwai " "2009-01-15 18:28:12 +0100" -"Johannes Berg " "2009-01-15 18:22:31 +0100" "Takashi Iwai " "2009-01-15 18:28:37 +0100" -"Hugo Villeneuve " "2009-01-15 15:40:35 -0500" "Mark Brown " "2009-01-15 23:43:54 +0000" -"Daniel Mack " "2009-01-16 11:03:19 +0100" "Takashi Iwai " "2009-01-16 11:36:47 +0100" -"Ian Molton " "2009-01-16 11:04:18 +0000" "Mark Brown " "2009-01-16 16:40:25 +0000" -"Mark Brown " "2009-01-16 16:31:03 +0000" "Mark Brown " "2009-01-16 18:00:33 +0000" -"Krzysztof Helt " "2009-01-16 22:47:30 +0100" "Takashi Iwai " "2009-01-17 12:02:21 +0100" -"Andreas Bergmeier " "2009-01-18 18:48:03 +0100" "Takashi Iwai " "2009-01-18 18:48:03 +0100" -"Takashi Iwai " "2009-01-19 14:30:48 +0100" "Takashi Iwai " "2009-01-19 14:30:48 +0100" -"Jaroslav Kysela " "2009-01-19 12:08:58 +0100" "Takashi Iwai " "2009-01-19 14:41:33 +0100" -"Mark Brown " "2009-01-16 16:35:52 +0000" "Mark Brown " "2009-01-19 16:15:35 +0000" -"Ian Molton " "2009-01-17 17:44:23 +0000" "Mark Brown " "2009-01-19 16:23:13 +0000" -"Mark Brown " "2009-01-17 19:14:26 +0000" "Mark Brown " "2009-01-19 16:23:27 +0000" -"Takashi Iwai " "2009-01-20 13:07:55 +0100" "Takashi Iwai " "2009-01-20 15:16:47 +0100" -"Takashi Iwai " "2009-01-20 15:28:38 +0100" "Takashi Iwai " "2009-01-20 15:31:14 +0100" -"Takashi Iwai " "2009-01-20 17:15:57 +0100" "Takashi Iwai " "2009-01-20 17:15:57 +0100" -"Takashi Iwai " "2009-01-20 17:17:29 +0100" "Takashi Iwai " "2009-01-20 17:18:41 +0100" -"Takashi Iwai " "2009-01-20 17:19:01 +0100" "Takashi Iwai " "2009-01-20 17:19:01 +0100" -"Takashi Iwai " "2009-01-20 18:21:23 +0100" "Takashi Iwai " "2009-01-20 18:21:23 +0100" -"Takashi Iwai " "2009-01-20 18:24:13 +0100" "Takashi Iwai " "2009-01-20 18:24:13 +0100" -"Takashi Iwai " "2009-01-20 18:30:20 +0100" "Takashi Iwai " "2009-01-20 18:30:20 +0100" -"Takashi Iwai " "2009-01-20 18:32:55 +0100" "Takashi Iwai " "2009-01-20 18:32:55 +0100" -"Timur Tabi " "2009-01-19 11:57:46 -0600" "Mark Brown " "2009-01-20 20:30:59 +0000" -"Ian Molton " "2009-01-19 17:23:11 +0000" "Mark Brown " "2009-01-20 20:36:52 +0000" -"Takashi Iwai " "2009-01-21 07:41:22 +0100" "Takashi Iwai " "2009-01-21 07:42:02 +0100" -"Takashi Iwai " "2009-01-21 07:43:23 +0100" "Takashi Iwai " "2009-01-21 07:43:23 +0100" -"Krzysztof Helt " "2009-01-21 08:18:16 +0100" "Takashi Iwai " "2009-01-21 08:36:39 +0100" -"Krzysztof Helt " "2009-01-21 08:19:27 +0100" "Takashi Iwai " "2009-01-21 08:37:04 +0100" -"Steve Sakoman " "2009-01-20 23:05:27 -0800" "Mark Brown " "2009-01-21 13:43:52 +0000" -"Krzysztof Helt " "2009-01-21 15:08:03 +0100" "Takashi Iwai " "2009-01-21 15:11:02 +0100" -"Takashi Iwai " "2009-01-22 16:59:20 +0100" "Takashi Iwai " "2009-01-22 16:59:20 +0100" -"Takashi Iwai " "2009-01-22 17:40:18 +0100" "Takashi Iwai " "2009-01-22 17:41:14 +0100" -"Matthew Ranostay " "2009-01-22 22:55:44 -0500" "Takashi Iwai " "2009-01-23 08:11:43 +0100" -"Takashi Iwai " "2009-01-23 09:09:43 +0100" "Takashi Iwai " "2009-01-23 09:09:43 +0100" -"Takashi Iwai " "2009-01-23 11:57:22 +0100" "Takashi Iwai " "2009-01-23 11:57:22 +0100" -"Timur Tabi " "2009-01-22 18:23:39 -0600" "Mark Brown " "2009-01-23 11:12:57 +0000" -"Mark Brown " "2009-01-23 11:23:32 +0000" "Mark Brown " "2009-01-23 11:23:32 +0000" -"Takashi Iwai " "2009-01-23 12:33:54 +0100" "Takashi Iwai " "2009-01-23 12:33:54 +0100" -"Takashi Iwai " "2009-01-23 12:35:25 +0100" "Takashi Iwai " "2009-01-23 12:35:25 +0100" -"Takashi Iwai " "2009-01-23 12:37:09 +0100" "Takashi Iwai " "2009-01-23 12:37:09 +0100" -"Mark Brown " "2009-01-23 11:40:26 +0000" "Mark Brown " "2009-01-23 11:40:26 +0000" -"Mark Brown " "2009-01-23 11:49:45 +0000" "Mark Brown " "2009-01-23 11:49:45 +0000" -"Takashi Iwai " "2009-01-23 12:53:09 +0100" "Takashi Iwai " "2009-01-23 12:53:09 +0100" -"Takashi Iwai " "2009-01-23 14:18:11 +0100" "Takashi Iwai " "2009-01-23 14:18:11 +0100" -"Markus Bollinger " "2009-01-23 14:45:41 +0100" "Takashi Iwai " "2009-01-23 14:45:41 +0100" -"Mark Brown " "2009-01-23 14:53:58 +0000" "Mark Brown " "2009-01-23 14:53:58 +0000" -"Mark Brown " "2009-01-23 15:07:45 +0000" "Mark Brown " "2009-01-23 15:07:45 +0000" -"Mark Brown " "2009-01-23 15:34:54 +0000" "Mark Brown " "2009-01-23 15:37:26 +0000" -"Timur Tabi " "2009-01-23 16:31:19 -0600" "Mark Brown " "2009-01-23 23:00:39 +0000" -"Matthew Ranostay " "2009-01-26 09:33:52 -0500" "Takashi Iwai " "2009-01-26 16:50:26 +0100" -"Clemens Ladisch " "2009-01-26 08:08:34 +0100" "Takashi Iwai " "2009-01-26 17:05:02 +0100" -"Clemens Ladisch " "2009-01-26 08:09:28 +0100" "Takashi Iwai " "2009-01-26 17:05:07 +0100" -"Clemens Ladisch " "2009-01-26 08:10:19 +0100" "Takashi Iwai " "2009-01-26 17:05:10 +0100" -"Andreas Bergmeier " "2009-01-24 12:15:14 +0100" "Takashi Iwai " "2009-01-27 11:40:13 +0100" -"Peter Ujfalusi " "2009-01-27 11:29:39 +0200" "Mark Brown " "2009-01-27 10:42:39 +0000" -"Peter Ujfalusi " "2009-01-27 11:29:40 +0200" "Mark Brown " "2009-01-27 10:42:39 +0000" -"Peter Ujfalusi " "2009-01-27 11:29:41 +0200" "Mark Brown " "2009-01-27 10:42:40 +0000" -"Peter Ujfalusi " "2009-01-27 11:29:42 +0200" "Mark Brown " "2009-01-27 10:43:02 +0000" -"Peter Ujfalusi " "2009-01-27 11:29:43 +0200" "Mark Brown " "2009-01-27 10:43:02 +0000" -"Krzysztof Helt " "2009-01-24 13:35:28 +0100" "Takashi Iwai " "2009-01-28 07:47:36 +0100" -"Takashi Iwai " "2009-01-28 08:23:03 +0100" "Takashi Iwai " "2009-01-28 08:23:03 +0100" -"Takashi Iwai " "2009-01-28 09:02:52 +0100" "Takashi Iwai " "2009-01-28 09:02:52 +0100" -"Thadeu Lima de Souza Cascardo " "2009-01-28 12:40:42 -0200" "Takashi Iwai " "2009-01-28 15:56:32 +0100" -"Takashi Iwai " "2009-01-28 16:05:16 +0100" "Takashi Iwai " "2009-01-28 16:05:16 +0100" -"Herton Ronaldo Krzesinski " "2009-01-28 09:16:33 -0200" "Takashi Iwai " "2009-01-28 16:25:39 +0100" -"Thadeu Lima de Souza Cascardo " "2009-01-28 15:39:22 -0200" "Takashi Iwai " "2009-01-29 08:38:36 +0100" -"Thadeu Lima de Souza Cascardo " "2009-01-28 18:20:06 -0200" "Takashi Iwai " "2009-01-29 08:38:56 +0100" -"Krzysztof Helt " "2009-01-29 11:44:24 +0100" "Takashi Iwai " "2009-01-29 11:46:25 +0100" -"Krzysztof Helt " "2009-01-29 11:46:45 +0100" "Takashi Iwai " "2009-01-29 11:46:56 +0100" -"Krzysztof Helt " "2009-01-29 11:48:14 +0100" "Takashi Iwai " "2009-01-29 11:47:02 +0100" -"Takashi Iwai " "2009-01-29 11:49:10 +0100" "Takashi Iwai " "2009-01-29 11:49:40 +0100" -"Peter Ujfalusi " "2009-01-29 14:57:50 +0200" "Mark Brown " "2009-01-29 13:58:04 +0000" -"Herton Ronaldo Krzesinski " "2009-01-29 13:18:31 -0200" "Takashi Iwai " "2009-01-29 16:33:02 +0100" -"Timur Tabi " "2009-01-29 14:28:37 -0600" "Mark Brown " "2009-01-30 11:58:50 +0000" -"Krzysztof Helt " "2009-01-30 19:20:29 +0100" "Takashi Iwai " "2009-01-30 19:55:37 +0100" -"Takashi Iwai " "2009-01-30 19:59:10 +0100" "Takashi Iwai " "2009-01-30 19:59:10 +0100" -"Timur Tabi " "2009-01-30 11:14:49 -0600" "Mark Brown " "2009-01-31 14:59:08 +0000" -"Grazvydas Ignotas " "2009-01-31 16:29:24 +0200" "Mark Brown " "2009-01-31 14:59:19 +0000" -"Tim Blechmann " "2009-01-31 18:01:13 +0100" "Takashi Iwai " "2009-01-31 18:01:13 +0100" -"Krzysztof Helt " "2009-02-01 21:13:15 +0100" "Takashi Iwai " "2009-02-02 08:24:36 +0100" -"Takashi Iwai " "2008-11-12 16:42:44 +0100" "Takashi Iwai " "2009-02-02 17:22:31 +0100" -"Timur Tabi " "2009-02-02 14:50:45 -0600" "Mark Brown " "2009-02-02 21:34:05 +0000" -"Timur Tabi " "2009-02-02 15:08:29 -0600" "Mark Brown " "2009-02-02 21:34:06 +0000" -"Tony Vroon " "2009-02-02 19:01:30 +0000" "Takashi Iwai " "2009-02-03 12:00:17 +0100" -"Tony Vroon " "2009-02-03 11:13:34 +0000" "Takashi Iwai " "2009-02-03 12:25:11 +0100" -"Vasily Khoruzhick " "2009-02-03 15:52:56 +0200" "Mark Brown " "2009-02-03 17:12:16 +0000" -"Philipp Zabel " "2009-02-03 17:19:40 +0100" "Mark Brown " "2009-02-04 13:15:15 +0000" -"Philipp Zabel " "2009-02-03 21:18:26 +0100" "Mark Brown " "2009-02-04 13:17:22 +0000" -"Kusanagi Kouichi " "2009-02-05 00:00:58 +0900" "Takashi Iwai " "2009-02-04 16:17:42 +0100" -"Krzysztof Helt " "2009-02-04 17:41:32 +0100" "Takashi Iwai " "2009-02-04 17:55:36 +0100" -"Takashi Iwai " "2009-02-04 18:28:42 +0100" "Takashi Iwai " "2009-02-04 18:28:42 +0100" -"Herton Ronaldo Krzesinski " "2009-02-04 11:23:19 -0500" "Takashi Iwai " "2009-02-05 07:54:32 +0100" -"Matthew Ranostay " "2009-02-04 17:49:41 -0500" "Takashi Iwai " "2009-02-05 08:01:01 +0100" -"Takashi Iwai " "2009-02-05 09:10:20 +0100" "Takashi Iwai " "2009-02-05 09:10:20 +0100" -"Takashi Iwai " "2009-02-05 09:17:50 +0100" "Takashi Iwai " "2009-02-05 09:17:50 +0100" -"Takashi Iwai " "2009-02-05 09:28:08 +0100" "Takashi Iwai " "2009-02-05 09:28:08 +0100" -"Mark Hills " "2009-02-04 22:34:30 +0000" "Takashi Iwai " "2009-02-05 09:31:53 +0100" -"Mark Hills " "2009-02-04 22:34:31 +0000" "Takashi Iwai " "2009-02-05 09:32:39 +0100" -"Mark Hills " "2009-02-04 22:34:32 +0000" "Takashi Iwai " "2009-02-05 09:33:24 +0100" -"Mark Hills " "2009-02-04 22:34:33 +0000" "Takashi Iwai " "2009-02-05 09:33:52 +0100" -"Mark Hills " "2009-02-04 22:34:34 +0000" "Takashi Iwai " "2009-02-05 09:34:13 +0100" -"Takashi Iwai " "2009-02-05 12:14:52 +0100" "Takashi Iwai " "2009-02-05 12:14:52 +0100" -"Takashi Iwai " "2009-02-05 15:02:06 +0100" "Takashi Iwai " "2009-02-05 15:02:40 +0100" -"Hans-Christian Egtvedt " "2009-02-05 13:11:01 +0100" "Takashi Iwai " "2009-02-05 15:08:53 +0100" -"Takashi Iwai " "2009-02-05 15:46:48 +0100" "Takashi Iwai " "2009-02-05 15:46:48 +0100" -"Takashi Iwai " "2009-02-05 15:47:51 +0100" "Takashi Iwai " "2009-02-05 15:48:34 +0100" -"Takashi Iwai " "2009-02-05 15:55:18 +0100" "Takashi Iwai " "2009-02-05 15:55:18 +0100" -"Takashi Iwai " "2009-02-05 15:57:55 +0100" "Takashi Iwai " "2009-02-05 15:58:32 +0100" -"Takashi Iwai " "2009-02-05 15:51:04 +0100" "Takashi Iwai " "2009-02-05 16:00:49 +0100" -"Takashi Iwai " "2009-02-05 15:51:50 +0100" "Takashi Iwai " "2009-02-05 16:00:56 +0100" -"Takashi Iwai " "2009-02-05 16:01:46 +0100" "Takashi Iwai " "2009-02-05 16:01:46 +0100" -"Takashi Iwai " "2009-02-05 16:07:02 +0100" "Takashi Iwai " "2009-02-05 16:07:02 +0100" -"Takashi Iwai " "2009-02-05 16:08:14 +0100" "Takashi Iwai " "2009-02-05 16:08:14 +0100" -"Takashi Iwai " "2009-02-05 16:09:57 +0100" "Takashi Iwai " "2009-02-05 16:09:57 +0100" -"Takashi Iwai " "2009-02-05 16:11:31 +0100" "Takashi Iwai " "2009-02-05 16:11:31 +0100" -"Takashi Iwai " "2009-02-05 16:11:58 +0100" "Takashi Iwai " "2009-02-05 16:11:58 +0100" -"Wu Fengguang " "2009-02-06 15:02:27 +0800" "Takashi Iwai " "2009-02-06 08:45:25 +0100" -"Mike Frysinger " "2009-02-06 18:12:34 +0800" "Mark Brown " "2009-02-06 12:07:29 +0000" -"Mike Frysinger " "2009-02-06 18:12:35 +0800" "Mark Brown " "2009-02-06 12:07:39 +0000" -"Timur Tabi " "2009-02-05 17:56:02 -0600" "Mark Brown " "2009-02-06 12:08:15 +0000" -"Takashi Iwai " "2009-02-06 16:11:25 +0100" "Takashi Iwai " "2009-02-06 16:13:29 +0100" -"Takashi Iwai " "2009-02-06 16:21:20 +0100" "Takashi Iwai " "2009-02-06 16:21:20 +0100" -"Takashi Iwai " "2009-02-06 16:48:10 +0100" "Takashi Iwai " "2009-02-06 16:48:10 +0100" -"Takashi Iwai " "2009-02-06 17:21:09 +0100" "Takashi Iwai " "2009-02-06 17:21:09 +0100" -"Takashi Iwai " "2009-02-06 17:22:05 +0100" "Takashi Iwai " "2009-02-06 17:22:05 +0100" -"Takashi Iwai " "2009-02-06 17:34:03 +0100" "Takashi Iwai " "2009-02-06 17:34:03 +0100" -"Robert Jarzmik " "2009-02-07 14:01:58 +0100" "Mark Brown " "2009-02-08 20:39:46 +0000" -"Roel Kluin " "2009-02-08 18:17:37 +0100" "Mark Brown " "2009-02-08 20:40:24 +0000" -"Philipp Zabel " "2009-02-05 17:48:21 +0100" "Mark Brown " "2009-02-08 20:40:26 +0000" -"Herton Ronaldo Krzesinski " "2009-02-08 19:50:34 -0200" "Takashi Iwai " "2009-02-09 08:25:08 +0100" -"Herton Ronaldo Krzesinski " "2009-02-08 19:51:28 -0200" "Takashi Iwai " "2009-02-09 08:25:23 +0100" -"Takashi Iwai " "2009-02-09 17:14:52 +0100" "Takashi Iwai " "2009-02-09 17:19:32 +0100" -"Takashi Iwai " "2009-02-09 17:15:50 +0100" "Takashi Iwai " "2009-02-09 17:20:19 +0100" -"Jarkko Nikula " "2009-02-09 14:27:06 +0200" "Mark Brown " "2009-02-09 18:27:59 +0000" -"Jarkko Nikula " "2009-02-09 14:27:07 +0200" "Mark Brown " "2009-02-09 18:27:59 +0000" -"Takashi Iwai " "2009-02-10 11:56:44 +0100" "Takashi Iwai " "2009-02-10 11:56:44 +0100" -"Takashi Iwai " "2009-02-11 08:28:04 +0100" "Takashi Iwai " "2009-02-11 08:28:04 +0100" -"Takashi Iwai " "2009-02-11 11:33:13 +0100" "Takashi Iwai " "2009-02-11 11:33:13 +0100" -"Takashi Iwai " "2009-02-11 11:35:15 +0100" "Takashi Iwai " "2009-02-12 00:04:19 +0100" -"Herton Ronaldo Krzesinski " "2009-02-11 20:33:15 -0200" "Takashi Iwai " "2009-02-12 00:17:31 +0100" -"Harvey Harrison " "2009-02-11 14:49:30 -0800" "Takashi Iwai " "2009-02-12 00:24:11 +0100" -"Takashi Iwai " "2009-02-13 08:16:55 +0100" "Takashi Iwai " "2009-02-13 08:16:55 +0100" -"Takashi Iwai " "2009-02-13 08:33:55 +0100" "Takashi Iwai " "2009-02-13 08:33:55 +0100" -"Matthew Ranostay " "2009-02-12 16:50:01 -0500" "Takashi Iwai " "2009-02-13 08:35:08 +0100" -"Aristeu Sergio Rozanski Filho " "2009-02-12 17:50:37 -0500" "Takashi Iwai " "2009-02-13 08:40:20 +0100" -"Takashi Iwai " "2009-02-13 09:31:20 +0100" "Takashi Iwai " "2009-02-13 09:31:20 +0100" -"Takashi Iwai " "2009-02-13 11:47:37 +0100" "Takashi Iwai " "2009-02-13 11:59:31 +0100" -"Takashi Iwai " "2009-02-13 11:19:09 +0100" "Takashi Iwai " "2009-02-13 11:59:33 +0100" -"Timur Tabi " "2009-02-03 11:09:32 -0600" "Mark Brown " "2009-02-13 13:32:51 +0000" -"Kevin Hilman " "2009-02-13 11:36:37 -0800" "Mark Brown " "2009-02-13 20:21:30 +0000" -"Herton Ronaldo Krzesinski " "2009-02-16 10:23:00 +0100" "Takashi Iwai " "2009-02-16 10:23:00 +0100" -"Takashi Iwai " "2009-02-16 14:16:36 +0100" "Takashi Iwai " "2009-02-16 14:16:36 +0100" -"Takashi Iwai " "2009-02-16 15:20:41 +0100" "Takashi Iwai " "2009-02-16 15:20:41 +0100" -"Krzysztof Helt " "2009-02-16 21:38:37 +0100" "Takashi Iwai " "2009-02-16 23:05:25 +0100" -"Takashi Iwai " "2009-02-16 23:17:33 +0100" "Takashi Iwai " "2009-02-16 23:17:33 +0100" -"Takashi Iwai " "2009-02-17 07:59:40 +0100" "Takashi Iwai " "2009-02-17 08:00:44 +0100" -"Takashi Iwai " "2009-02-17 08:10:54 +0100" "Takashi Iwai " "2009-02-17 08:10:54 +0100" -"Paul Fertser " "2009-02-16 02:49:41 +0300" "Mark Brown " "2009-02-17 14:29:54 +0000" -"Mark Brown " "2009-02-16 14:08:22 +0000" "Mark Brown " "2009-02-17 14:29:54 +0000" -"Mark Brown " "2009-02-16 19:20:15 +0000" "Mark Brown " "2009-02-17 14:29:54 +0000" -"Mark Brown " "2009-02-16 13:38:11 +0000" "Mark Brown " "2009-02-18 11:25:21 +0000" -"Mark Brown " "2009-02-16 16:04:05 +0000" "Mark Brown " "2009-02-18 11:25:22 +0000" -"Mark Brown " "2009-02-16 17:51:54 +0000" "Mark Brown " "2009-02-18 11:25:23 +0000" -"Mark Brown " "2009-02-16 18:00:58 +0000" "Mark Brown " "2009-02-18 11:25:23 +0000" -"Mark Brown " "2009-02-16 19:35:43 +0000" "Mark Brown " "2009-02-18 11:25:48 +0000" -"Mark Brown " "2009-02-16 20:49:16 +0000" "Mark Brown " "2009-02-18 11:55:22 +0000" -"Mark Brown " "2009-02-18 11:36:44 +0000" "Mark Brown " "2009-02-18 11:55:26 +0000" -"Takashi Iwai " "2009-02-18 13:16:26 +0100" "Takashi Iwai " "2009-02-18 13:16:26 +0100" -"Mark Brown " "2009-02-18 12:34:53 +0000" "Mark Brown " "2009-02-18 14:46:58 +0000" -"Mark Brown " "2009-02-18 12:44:40 +0000" "Mark Brown " "2009-02-18 14:47:20 +0000" -"Peter Ujfalusi " "2009-02-18 14:39:05 +0200" "Mark Brown " "2009-02-18 17:14:23 +0000" -"Mark Brown " "2009-02-18 21:06:01 +0000" "Mark Brown " "2009-02-18 21:06:01 +0000" -"Mark Brown " "2009-02-18 21:25:40 +0000" "Mark Brown " "2009-02-18 21:26:58 +0000" -"Takashi Iwai " "2009-02-19 08:06:35 +0100" "Takashi Iwai " "2009-02-19 08:06:35 +0100" -"Takashi Iwai " "2009-02-19 08:13:26 +0100" "Takashi Iwai " "2009-02-19 08:13:26 +0100" -"Takashi Iwai " "2009-02-19 08:15:49 +0100" "Takashi Iwai " "2009-02-19 08:15:49 +0100" -"Clemens Ladisch " "2009-02-19 08:37:13 +0100" "Takashi Iwai " "2009-02-19 10:22:22 +0100" -"Clemens Ladisch " "2009-02-19 08:38:25 +0100" "Takashi Iwai " "2009-02-19 10:22:23 +0100" -"Clemens Ladisch " "2009-02-19 08:38:55 +0100" "Takashi Iwai " "2009-02-19 10:22:24 +0100" -"Clemens Ladisch " "2009-02-19 08:42:44 +0100" "Takashi Iwai " "2009-02-19 10:22:25 +0100" -"Clemens Ladisch " "2009-02-19 08:44:12 +0100" "Takashi Iwai " "2009-02-19 10:22:26 +0100" -"Mark Brown " "2009-02-19 14:29:49 +0000" "Mark Brown " "2009-02-19 14:30:57 +0000" -"Clemens Ladisch " "2009-02-20 09:31:14 +0100" "Takashi Iwai " "2009-02-20 11:14:09 +0100" -"Clemens Ladisch " "2009-02-20 09:33:40 +0100" "Takashi Iwai " "2009-02-20 11:14:25 +0100" -"Clemens Ladisch " "2009-02-20 09:32:40 +0100" "Takashi Iwai " "2009-02-20 11:14:55 +0100" -"Takashi Iwai " "2009-02-20 14:11:16 +0100" "Takashi Iwai " "2009-02-20 16:48:26 +0100" -"Takashi Iwai " "2009-02-20 14:13:06 +0100" "Takashi Iwai " "2009-02-20 16:48:38 +0100" -"Takashi Iwai " "2009-02-20 14:33:36 +0100" "Takashi Iwai " "2009-02-20 16:48:39 +0100" -"Takashi Iwai " "2009-02-20 14:37:42 +0100" "Takashi Iwai " "2009-02-20 16:48:40 +0100" -"Takashi Iwai " "2009-02-20 14:50:35 +0100" "Takashi Iwai " "2009-02-20 16:48:40 +0100" -"Mark Brown " "2009-02-22 14:19:23 +0000" "Mark Brown " "2009-02-22 14:19:23 +0000" -"Mark Brown " "2009-02-22 14:24:00 +0000" "Mark Brown " "2009-02-22 14:24:00 +0000" -"Michael Schwingen " "2009-02-22 18:58:45 +0100" "Takashi Iwai " "2009-02-23 07:39:34 +0100" -"Andreas Mohr " "2009-02-22 20:33:41 +0100" "Takashi Iwai " "2009-02-23 07:47:52 +0100" -"Tim Blechmann " "2009-02-20 19:30:35 +0100" "Takashi Iwai " "2009-02-23 08:20:01 +0100" -"Tim Blechmann " "2009-02-20 19:38:16 +0100" "Takashi Iwai " "2009-02-23 08:28:02 +0100" -"Takashi Iwai " "2009-02-23 09:28:12 +0100" "Takashi Iwai " "2009-02-23 09:28:12 +0100" -"Takashi Iwai " "2009-02-23 09:42:57 +0100" "Takashi Iwai " "2009-02-23 09:42:57 +0100" -"Takashi Iwai " "2009-02-23 09:45:59 +0100" "Takashi Iwai " "2009-02-23 09:45:59 +0100" -"Takashi Iwai " "2009-02-23 11:33:34 +0100" "Takashi Iwai " "2009-02-23 11:33:34 +0100" -"Takashi Iwai " "2009-02-23 14:14:51 +0100" "Takashi Iwai " "2009-02-23 14:14:51 +0100" -"Takashi Iwai " "2009-02-23 16:57:04 +0100" "Takashi Iwai " "2009-02-23 16:57:04 +0100" -"Mark Brown " "2009-01-23 14:44:54 +0000" "Mark Brown " "2009-02-24 23:48:11 +0000" -"Mark Brown " "2009-02-23 18:45:19 +0000" "Mark Brown " "2009-02-24 23:48:12 +0000" -"Mark Brown " "2009-02-22 14:39:03 +0000" "Mark Brown " "2009-02-24 23:48:14 +0000" -"Mark Brown " "2009-02-24 23:33:12 +0000" "Mark Brown " "2009-02-24 23:49:53 +0000" -"Mark Brown " "2009-02-22 20:04:41 +0000" "Mark Brown " "2009-02-24 23:49:56 +0000" -"Takashi Iwai " "2009-02-25 18:12:13 +0100" "Takashi Iwai " "2009-02-25 18:12:13 +0100" -"Takashi Iwai " "2009-02-26 00:57:01 +0100" "Takashi Iwai " "2009-02-26 00:57:01 +0100" -"Clemens Ladisch " "2009-02-26 09:27:20 +0100" "Takashi Iwai " "2009-02-26 09:39:08 +0100" -"Hannes Eder " "2009-02-25 22:26:48 +0100" "Takashi Iwai " "2009-02-26 09:57:17 +0100" -"Hannes Eder " "2009-02-25 22:28:26 +0100" "Takashi Iwai " "2009-02-26 09:57:19 +0100" -"Hannes Eder " "2009-02-25 22:29:15 +0100" "Takashi Iwai " "2009-02-26 09:57:21 +0100" -"Hannes Eder " "2009-02-25 22:28:59 +0100" "Takashi Iwai " "2009-02-26 09:57:53 +0100" -"Hannes Eder " "2009-02-25 22:28:45 +0100" "Takashi Iwai " "2009-02-26 09:59:04 +0100" -"Takashi Iwai " "2009-02-26 11:29:58 +0100" "Takashi Iwai " "2009-02-26 11:29:58 +0100" -"Takashi Iwai " "2009-02-26 13:03:58 +0100" "Takashi Iwai " "2009-02-26 13:03:58 +0100" -"Takashi Iwai " "2009-02-26 16:50:43 +0100" "Takashi Iwai " "2009-02-26 16:50:43 +0100" -"peerchen " "2009-02-27 17:03:19 +0800" "Takashi Iwai " "2009-02-27 10:22:55 +0100" -"Clemens Ladisch " "2009-02-27 09:27:44 +0100" "Takashi Iwai " "2009-02-27 17:32:21 +0100" -"Takashi Iwai " "2009-02-27 17:52:22 +0100" "Takashi Iwai " "2009-02-27 17:52:22 +0100" -"Ben Dooks " "2009-02-28 17:09:57 +0000" "Mark Brown " "2009-02-28 17:18:24 +0000" -"Daniel Mack " "2009-02-25 14:37:21 +0100" "Mark Brown " "2009-02-28 17:18:25 +0000" -"Mark Brown " "2009-02-28 21:14:20 +0000" "Mark Brown " "2009-02-28 21:31:21 +0000" -"Takashi Iwai " "2009-03-02 08:04:35 +0100" "Takashi Iwai " "2009-03-02 08:04:35 +0100" -"Takashi Iwai " "2009-03-02 10:35:29 +0100" "Takashi Iwai " "2009-03-02 10:35:29 +0100" -"Takashi Iwai " "2009-03-02 10:44:15 +0100" "Takashi Iwai " "2009-03-02 10:44:15 +0100" -"Takashi Iwai " "2009-03-02 10:46:03 +0100" "Takashi Iwai " "2009-03-02 10:46:30 +0100" -"Clemens Ladisch " "2009-03-02 11:45:50 +0100" "Takashi Iwai " "2009-03-02 14:49:58 +0100" -"Clemens Ladisch " "2009-03-02 12:06:28 +0100" "Takashi Iwai " "2009-03-02 14:50:01 +0100" -"Daniel Mack " "2009-02-28 13:21:03 +0100" "Mark Brown " "2009-03-02 14:39:23 +0000" -"Takashi Iwai " "2009-03-02 14:25:17 +0100" "Takashi Iwai " "2009-03-02 17:28:54 +0100" -"Takashi Iwai " "2009-03-02 17:09:25 +0100" "Takashi Iwai " "2009-03-02 17:29:53 +0100" -"Takashi Iwai " "2009-03-02 14:26:25 +0100" "Takashi Iwai " "2009-03-02 17:30:00 +0100" -"Takashi Iwai " "2009-03-02 14:38:35 +0100" "Takashi Iwai " "2009-03-02 17:30:00 +0100" -"Takashi Iwai " "2009-03-02 17:34:51 +0100" "Takashi Iwai " "2009-03-02 17:34:51 +0100" -"Takashi Iwai " "2009-03-03 15:00:35 +0100" "Takashi Iwai " "2009-03-03 15:00:35 +0100" -"Philipp Zabel " "2009-03-03 16:10:53 +0100" "Mark Brown " "2009-03-03 15:54:10 +0000" -"Philipp Zabel " "2009-03-03 16:10:54 +0100" "Mark Brown " "2009-03-03 15:54:10 +0000" -"Philipp Zabel " "2009-03-03 16:10:51 +0100" "Mark Brown " "2009-03-03 15:54:11 +0000" -"Philipp Zabel " "2009-03-03 16:10:52 +0100" "Mark Brown " "2009-03-03 15:58:51 +0000" -"Takashi Iwai " "2009-03-04 09:03:50 +0100" "Takashi Iwai " "2009-03-04 09:03:50 +0100" -"Takashi Iwai " "2009-03-04 11:30:25 +0100" "Takashi Iwai " "2009-03-04 11:30:25 +0100" -"Lopez Cruz, Misael " "2009-03-03 15:25:04 -0600" "Mark Brown " "2009-03-04 14:47:38 +0000" -"Jonas Andersson " "2009-03-04 08:24:26 +0100" "Mark Brown " "2009-03-04 14:47:39 +0000" -"Herton Ronaldo Krzesinski " "2009-03-04 14:22:50 -0300" "Takashi Iwai " "2009-03-04 21:05:11 +0100" -"Herton Ronaldo Krzesinski " "2009-03-04 14:22:51 -0300" "Takashi Iwai " "2009-03-04 21:05:25 +0100" -"Herton Ronaldo Krzesinski " "2009-03-04 14:22:52 -0300" "Takashi Iwai " "2009-03-04 21:05:40 +0100" -"Takashi Iwai " "2009-03-05 09:37:40 +0100" "Takashi Iwai " "2009-03-05 09:37:40 +0100" -"Takashi Iwai " "2009-03-05 09:40:16 +0100" "Takashi Iwai " "2009-03-05 09:40:16 +0100" -"Takashi Iwai " "2009-03-05 14:18:16 +0100" "Takashi Iwai " "2009-03-05 14:18:26 +0100" -"Takashi Iwai " "2009-03-06 10:00:05 +0100" "Takashi Iwai " "2009-03-06 10:04:24 +0100" -"Takashi Iwai " "2009-03-06 10:08:14 +0100" "Takashi Iwai " "2009-03-06 10:08:14 +0100" -"Takashi Iwai " "2009-03-06 10:13:24 +0100" "Takashi Iwai " "2009-03-06 10:13:24 +0100" -"Takashi Iwai " "2009-03-06 12:00:24 +0100" "Takashi Iwai " "2009-03-06 12:00:24 +0100" -"Takashi Iwai " "2009-03-06 12:10:41 +0100" "Takashi Iwai " "2009-03-06 12:10:41 +0100" -"Takashi Iwai " "2009-03-06 14:30:08 +0100" "Takashi Iwai " "2009-03-06 14:30:08 +0100" -"Lopez Cruz, Misael " "2009-03-04 11:39:07 -0600" "Mark Brown " "2009-03-06 13:37:06 +0000" -"Ben Dooks " "2009-03-04 00:49:27 +0000" "Mark Brown " "2009-03-06 13:37:07 +0000" -"Ben Dooks " "2009-03-04 00:49:30 +0000" "Mark Brown " "2009-03-06 13:37:08 +0000" -"Ben Dooks " "2009-03-04 00:49:34 +0000" "Mark Brown " "2009-03-06 13:37:09 +0000" -"Mark Brown " "2009-03-04 20:17:48 +0000" "Mark Brown " "2009-03-06 13:37:10 +0000" -"Peter Ujfalusi " "2009-03-05 12:48:49 +0200" "Mark Brown " "2009-03-06 13:37:11 +0000" -"Mark Brown " "2009-03-01 19:21:10 +0000" "Mark Brown " "2009-03-06 13:37:13 +0000" -"Mark Brown " "2009-03-05 17:06:23 +0000" "Mark Brown " "2009-03-06 13:37:14 +0000" -"Mark Brown " "2009-03-05 17:26:15 +0000" "Mark Brown " "2009-03-06 13:37:15 +0000" -"Timur Tabi " "2009-03-05 17:23:37 -0600" "Mark Brown " "2009-03-06 13:37:16 +0000" -"Lopez Cruz, Misael " "2009-03-05 11:32:31 -0600" "Mark Brown " "2009-03-06 13:37:17 +0000" -"Mike Frysinger " "2009-03-06 15:53:28 +0800" "Mark Brown " "2009-03-06 13:37:17 +0000" -"Mike Frysinger " "2009-03-06 15:53:30 +0800" "Mark Brown " "2009-03-06 13:37:18 +0000" -"Mark Brown " "2009-03-06 11:32:17 +0000" "Mark Brown " "2009-03-06 13:37:19 +0000" -"Mark Brown " "2009-03-06 18:04:34 +0000" "Mark Brown " "2009-03-06 18:04:34 +0000" -"Mark Brown " "2009-03-06 18:13:43 +0000" "Mark Brown " "2009-03-06 18:13:43 +0000" -"Hugo Villeneuve " "2009-03-06 15:56:53 -0500" "Mark Brown " "2009-03-07 11:01:40 +0000" -"Timur Tabi " "2009-03-06 18:39:34 -0600" "Mark Brown " "2009-03-07 11:01:49 +0000" -"Daniel Mack " "2009-03-08 17:51:52 +0100" "Mark Brown " "2009-03-08 18:27:36 +0000" -"Mark Brown " "2009-03-08 18:57:34 +0000" "Mark Brown " "2009-03-08 20:43:33 +0000" -"Takashi Iwai " "2009-03-09 00:52:17 +0100" "Takashi Iwai " "2009-03-09 00:52:17 +0100" -"Clemens Ladisch " "2009-03-09 09:12:55 +0100" "Takashi Iwai " "2009-03-09 09:45:11 +0100" -"Daniel Mack " "2009-03-09 02:13:17 +0100" "Mark Brown " "2009-03-09 10:46:17 +0000" -"Takashi Iwai " "2009-03-03 17:00:15 +0100" "Takashi Iwai " "2009-03-09 12:56:49 +0100" -"Risto Suominen " "2009-01-20 22:01:13 +0200" "Takashi Iwai " "2009-03-09 14:58:01 +0100" -"Risto Suominen " "2009-01-20 22:01:14 +0200" "Takashi Iwai " "2009-03-09 14:58:07 +0100" -"Risto Suominen " "2009-01-20 22:01:15 +0200" "Takashi Iwai " "2009-03-09 14:58:13 +0100" -"Risto Suominen " "2009-01-20 22:01:16 +0200" "Takashi Iwai " "2009-03-09 14:58:19 +0100" -"Risto Suominen " "2009-01-20 22:01:17 +0200" "Takashi Iwai " "2009-03-09 14:58:26 +0100" -"Takashi Iwai " "2009-02-05 16:02:46 +0100" "Takashi Iwai " "2009-03-09 14:58:31 +0100" -"Roel Kluin " "2009-02-25 13:40:26 +0100" "Takashi Iwai " "2009-03-09 14:58:37 +0100" -"Takashi Iwai " "2009-02-09 08:53:50 +0100" "Takashi Iwai " "2009-03-09 15:12:34 +0100" -"Takashi Iwai " "2009-02-11 14:55:59 +0100" "Takashi Iwai " "2009-03-09 15:17:21 +0100" -"Takashi Iwai " "2009-02-09 08:50:43 +0100" "Takashi Iwai " "2009-03-09 15:22:41 +0100" -"Mark Brown " "2009-03-09 18:18:33 +0000" "Mark Brown " "2009-03-09 18:19:01 +0000" -"Christoph Plattner " "2009-03-08 23:19:05 +0100" "Takashi Iwai " "2009-03-10 07:35:20 +0100" -"Christoph Plattner " "2009-03-10 00:05:56 +0100" "Takashi Iwai " "2009-03-10 07:36:19 +0100" -"Takashi Iwai " "2009-03-10 07:48:57 +0100" "Takashi Iwai " "2009-03-10 07:49:50 +0100" -"Takashi Iwai " "2009-03-10 07:54:20 +0100" "Takashi Iwai " "2009-03-10 07:54:20 +0100" -"Takashi Iwai " "2009-03-10 14:30:40 +0100" "Takashi Iwai " "2009-03-10 15:13:17 +0100" -"Takashi Iwai " "2009-03-10 14:41:05 +0100" "Takashi Iwai " "2009-03-10 15:13:23 +0100" -"Takashi Iwai " "2009-03-10 14:53:54 +0100" "Takashi Iwai " "2009-03-10 15:13:24 +0100" -"Takashi Iwai " "2009-03-10 15:10:55 +0100" "Takashi Iwai " "2009-03-10 15:13:25 +0100" -"Takashi Iwai " "2009-03-10 15:35:35 +0100" "Takashi Iwai " "2009-03-10 15:35:35 +0100" -"Hugo Villeneuve " "2009-03-09 23:32:07 -0400" "Mark Brown " "2009-03-10 15:42:48 +0000" -"Hugo Villeneuve " "2009-03-09 23:32:08 -0400" "Mark Brown " "2009-03-10 15:42:48 +0000" -"Daniel Mack " "2009-03-10 16:41:00 +0100" "Mark Brown " "2009-03-10 19:44:04 +0000" -"Takashi Iwai " "2009-03-11 09:50:19 +0100" "Takashi Iwai " "2009-03-11 09:50:19 +0100" -"Takashi Iwai " "2009-03-11 09:52:28 +0100" "Takashi Iwai " "2009-03-11 09:55:03 +0100" -"David Brownell " "2009-03-11 02:37:25 -0800" "Mark Brown " "2009-03-11 12:49:28 +0000" -"Mark Brown " "2009-03-11 14:12:28 +0000" "Mark Brown " "2009-03-11 14:40:41 +0000" -"Mark Brown " "2009-03-11 16:28:29 +0000" "Mark Brown " "2009-03-11 16:28:29 +0000" -"Gregorio Guidi " "2009-03-12 16:41:51 +0100" "Takashi Iwai " "2009-03-12 16:41:51 +0100" -"Mark Brown " "2009-03-11 18:31:08 +0000" "Mark Brown " "2009-03-12 15:43:24 +0000" -"Philipp Zabel " "2009-03-12 11:07:54 +0100" "Mark Brown " "2009-03-12 15:43:30 +0000" -"Takashi Iwai " "2009-03-12 16:45:01 +0100" "Takashi Iwai " "2009-03-12 16:45:01 +0100" -"Takashi Iwai " "2009-03-12 17:06:07 +0100" "Takashi Iwai " "2009-03-12 17:06:07 +0100" -"Takashi Iwai " "2009-03-12 18:17:58 +0100" "Takashi Iwai " "2009-03-12 18:17:58 +0100" -"Takashi Iwai " "2009-03-13 09:02:42 +0100" "Takashi Iwai " "2009-03-13 09:06:31 +0100" -"Lopez Cruz, Misael " "2009-03-12 21:45:27 -0500" "Mark Brown " "2009-03-13 12:08:53 +0000" -"Daniel Mack " "2009-03-12 11:27:49 +0100" "Mark Brown " "2009-03-13 13:23:34 +0000" -"Takashi Iwai " "2009-03-13 17:04:34 +0100" "Takashi Iwai " "2009-03-13 17:04:34 +0100" -"Mark Brown " "2009-03-13 14:26:08 +0000" "Mark Brown " "2009-03-14 11:37:46 +0000" -"Mark Brown " "2009-03-13 14:27:08 +0000" "Mark Brown " "2009-03-14 11:38:16 +0000" -"Giuliano Pochini " "2009-03-15 21:33:34 +0100" "Takashi Iwai " "2009-03-16 08:37:29 +0100" -"Giuliano Pochini " "2009-03-15 21:33:55 +0100" "Takashi Iwai " "2009-03-16 08:38:00 +0100" -"Joonyoung Shim " "2009-03-16 21:23:35 +0900" "Mark Brown " "2009-03-16 14:13:56 +0000" -"Mark Brown " "2009-03-16 14:02:07 +0000" "Mark Brown " "2009-03-16 14:13:57 +0000" -"Mark Brown " "2009-03-16 14:13:12 +0000" "Mark Brown " "2009-03-16 14:13:57 +0000" -"Jaroslav Kysela " "2009-03-16 14:56:58 +0100" "Takashi Iwai " "2009-03-16 15:23:33 +0100" -"Takashi Iwai " "2009-03-16 15:25:00 +0100" "Takashi Iwai " "2009-03-16 15:26:01 +0100" -"Atsushi Nemoto " "2009-03-16 23:26:20 +0900" "Mark Brown " "2009-03-17 13:59:47 +0000" -"Jaroslav Kysela " "2009-03-17 14:30:31 +0100" "Takashi Iwai " "2009-03-18 07:50:44 +0100" -"Daniel Mack " "2009-03-18 11:03:53 +0100" "Takashi Iwai " "2009-03-18 11:27:51 +0100" -"Daniel Mack " "2009-03-18 11:03:54 +0100" "Takashi Iwai " "2009-03-18 11:31:08 +0100" -"Daniel Mack " "2009-03-18 11:03:55 +0100" "Takashi Iwai " "2009-03-18 11:31:26 +0100" -"Mark Brown " "2009-03-18 15:19:10 +0000" "Mark Brown " "2009-03-18 18:31:53 +0000" -"Mark Brown " "2009-03-18 15:19:48 +0000" "Mark Brown " "2009-03-18 18:31:54 +0000" -"Giuliano Pochini " "2009-03-19 00:09:03 +0100" "Takashi Iwai " "2009-03-19 08:17:57 +0100" -"Takashi Iwai " "2009-03-19 09:55:15 +0100" "Takashi Iwai " "2009-03-19 09:57:45 +0100" -"Takashi Iwai " "2009-03-19 09:59:21 +0100" "Takashi Iwai " "2009-03-19 09:59:21 +0100" -"Takashi Iwai " "2009-03-19 10:01:47 +0100" "Takashi Iwai " "2009-03-19 10:01:47 +0100" -"Takashi Iwai " "2009-03-19 10:08:49 +0100" "Takashi Iwai " "2009-03-19 10:08:49 +0100" -"Takashi Iwai " "2009-03-18 15:09:13 +0100" "Takashi Iwai " "2009-03-19 12:53:58 +0100" -"Takashi Iwai " "2009-03-18 15:15:37 +0100" "Takashi Iwai " "2009-03-19 12:54:23 +0100" -"Mark Brown " "2009-03-18 18:28:01 +0000" "Mark Brown " "2009-03-19 11:56:11 +0000" -"Jarkko Nikula " "2009-03-18 16:46:53 +0200" "Mark Brown " "2009-03-19 11:56:15 +0000" -"Jarkko Nikula " "2009-03-18 16:46:54 +0200" "Mark Brown " "2009-03-19 11:56:16 +0000" -"Lopez Cruz, Misael " "2009-03-19 01:07:34 -0500" "Mark Brown " "2009-03-19 11:56:16 +0000" -"Takashi Iwai " "2009-03-19 14:08:58 +0100" "Takashi Iwai " "2009-03-19 14:16:19 +0100" -"Takashi Iwai " "2009-03-19 17:08:19 +0100" "Takashi Iwai " "2009-03-19 17:08:19 +0100" -"Wolfram Sang " "2009-03-20 10:08:11 +0100" "Takashi Iwai " "2009-03-20 12:47:50 +0100" -"Takashi Iwai " "2009-03-20 12:52:47 +0100" "Takashi Iwai " "2009-03-20 12:52:47 +0100" -"Takashi Iwai " "2009-03-20 16:26:15 +0100" "Takashi Iwai " "2009-03-20 16:26:15 +0100" -"Pascal de Bruijn " "2009-03-23 11:15:59 +0100" "Takashi Iwai " "2009-03-23 11:55:36 +0100" -"Takashi Iwai " "2009-03-23 12:51:55 +0100" "Takashi Iwai " "2009-03-23 12:51:55 +0100" -"Takashi Iwai " "2009-03-23 13:07:47 +0100" "Takashi Iwai " "2009-03-23 13:08:33 +0100" -"Takashi Iwai " "2009-03-23 15:17:38 +0100" "Takashi Iwai " "2009-03-23 15:20:53 +0100" -"Takashi Iwai " "2009-03-23 15:21:36 +0100" "Takashi Iwai " "2009-03-23 15:24:15 +0100" -"Takashi Iwai " "2009-03-23 16:35:39 +0100" "Takashi Iwai " "2009-03-23 16:36:55 +0100" -"Takashi Iwai " "2009-03-23 22:50:52 +0100" "Takashi Iwai " "2009-03-23 22:50:52 +0100" -"Clemens Ladisch " "2009-04-03 09:41:40 +0200" "Takashi Iwai " "2009-04-07 04:11:16 +0200" -"Clemens Ladisch " "2009-04-03 09:42:42 +0200" "Takashi Iwai " "2009-04-07 04:11:21 +0200" -"Clemens Ladisch " "2009-04-03 09:45:01 +0200" "Takashi Iwai " "2009-04-07 04:11:24 +0200" -"Clemens Ladisch " "2009-04-03 09:48:26 +0200" "Takashi Iwai " "2009-04-07 04:11:28 +0200" -"Mark Brown " "2009-01-03 16:56:56 +0000" "Mark Brown " "2009-01-03 17:02:21 +0000" -"Mark Brown " "2009-01-23 22:55:23 +0000" "Mark Brown " "2009-01-27 10:30:54 +0000" -"Eric Miao " "2009-03-03 09:41:00 +0800" "Mark Brown " "2009-03-04 22:29:47 +0000" -"Robert Jarzmik " "2009-03-15 14:10:54 +0100" "Mark Brown " "2009-03-15 20:20:37 +0000" -"Arnd Bergmann " "2009-02-26 09:57:27 +0100" "Ingo Molnar " "2009-03-26 18:14:24 +0100" -"Mauro Carvalho Chehab " "2009-02-27 11:51:24 -0300" "Mauro Carvalho Chehab " "2009-03-30 12:43:02 -0300" -"Philipp Zabel " "2009-03-19 09:32:01 +0100" "Mark Brown " "2009-04-02 16:34:13 +0100" -"Philipp Zabel " "2009-03-19 09:34:46 +0100" "Mark Brown " "2009-04-02 16:34:13 +0100" -"Timur Tabi " "2009-03-25 18:20:37 -0500" "Mark Brown " "2009-04-02 16:34:14 +0100" -"Luotao Fu " "2009-03-26 13:18:03 +0100" "Mark Brown " "2009-04-02 16:34:15 +0100" -"Timur Tabi " "2009-03-26 11:42:38 -0500" "Mark Brown " "2009-04-02 16:34:15 +0100" -"Peter Ujfalusi " "2009-03-27 10:39:07 +0200" "Mark Brown " "2009-04-02 16:34:16 +0100" -"Peter Ujfalusi " "2009-03-27 10:39:08 +0200" "Mark Brown " "2009-04-02 16:34:16 +0100" -"Jarkko Nikula " "2009-03-27 15:32:01 +0200" "Mark Brown " "2009-04-02 16:34:17 +0100" diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..ecfbcbb --- /dev/null +++ b/utils.py @@ -0,0 +1,162 @@ +#! /usr/bin/python +# -*- Python -*- + +import os +import sys +import config + +def package(repo): + if repo == 'alsa-python': + return 'pyalsa' + return repo + +def tmpdir(extra=''): + if not os.path.exists(config.TMPDIR): + os.mkdir(config.TMPDIR) + if extra and extra[0] != '/': + extra = '/' + extra + if extra and not os.path.exists(config.TMPDIR + extra): + os.mkdir(config.TMPDIR + extra) + return os.path.abspath(config.TMPDIR + extra) + +def tmpfile(file, extra=''): + return tmpdir(extra) + '/' + file + +def eprint(msg): + sys.stderr.write(msg + '\n') + +def is_alsa_file(file): + for i in config.NOT_ALSA_FILES: + if file.startswith(i): + return False + for i in config.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 config.ALSA_TRANSLATE: + if gitfile.startswith(i): + return prefix + config.ALSA_TRANSLATE[i] + gitfile[len(i):] + raise ValueError, repr(gitfile) + +def to_kernel_file(gitfile, prefix=''): + if gitfile == '/dev/null': + return '/dev/null' + if prefix and gitfile.startswith(prefix): + gitfile = gitfile[len(prefix):] + for i in config.ALSA_RTRANSLATE: + if gitfile.startswith(i): + return prefix + config.ALSA_RTRANSLATE[i] + gitfile[len(i):] + raise ValueError, repr(gitfile) + +def git_repo(repo): + if repo == '.': + return os.path.abspath(repo) + if repo[0] != '/': + repo = config.ROOT + '/' + repo + return os.path.abspath(repo) + +def git(repo): + repo = git_repo(repo) + return "LANG=C git --work-tree=%s --git-dir=%s" % (repo, repo + '/.git') + +def git_popen(repo, cmd): + return os.popen("%s %s" % (git(repo), cmd)) + +def git_system(repo, cmd, exports=None): + if exports is None: + exports = '' + else: + exports += ' ; ' + return os.system("%s%s %s" % (exports, git(repo), cmd)) + +def git_read_commits(repo, old, head, kernel_tree=False, reverse=False): + + def check_files(): + commit['comment'] = commit['comment'].strip() + if not kernel_tree: + return True + for file in commit['files']: + if is_alsa_file(file): + return True + return False + + reverse = reverse and " --reverse" or "" + curdir = os.getcwd() + os.chdir(git_repo(repo)) + if old.startswith('__'): + fp = git_popen(repo, "log --name-only --pretty=fuller --date=iso%s %s %s" % (reverse, old[2:], head)) + else: + print 'Analyzing %s %s..%s:' % (repo, old, head) + fp = git_popen(repo, "log --name-only --pretty=fuller --date=iso%s %s..%s" % (reverse, old, head)) + res = [] + commit = None + while 1: + line = fp.readline() + if not line: + break + if line.startswith('commit '): + if commit is not None and check_files(): + res.append(commit) + commit = {'comment':'', 'files':[]} + commit['ref'] = line[7:].strip() + elif line.startswith('Author:') or line.startswith('AuthorDate:') or \ + line.startswith('Commit:') or line.startswith('CommitDate:') or \ + line.startswith('Merge:'): + line = line.replace('Signed-off-by:', '') + a = line.split(': ') + commit[a[0].strip()] = a[-1].strip() + elif line.startswith(' '): + commit['comment'] += line[4:].strip() + '\n' + else: + line = line.strip() + if line: + commit['files'].append(line) + if commit is not None and check_files(): + res.append(commit) + fp.close() + if not old.startswith('__'): + print ' %s commits read' % len(res) + os.chdir(curdir) + return res + +def diff_compare2(diff1, diff2): + if len(diff1) != len(diff2): + return False + for idx in range(0, len(diff1)-1): + if diff1[idx].startswith('index ') and diff2[idx].startswith('index '): + continue + elif diff1[idx].startswith('@@ ') and diff2[idx].startswith('@@ '): + a = diff1[idx].split(' ') + b = diff2[idx].split(' ') + a1 = a[1].split(',') + a2 = a[2].split(',') + b1 = b[1].split(',') + b2 = b[2].split(',') + if len(a1) < 2: + a1.append('XXX') + if len(b1) < 2: + b1.append('XXX') + if a1[1] != b1[1] or a2[1] != b2[1]: + return False + elif diff1[idx] != diff2[idx]: + return False + return True + +def diff_compare(repo1, commit1, repo2, commit2): + diff1 = git_popen(repo1, "diff %s~1..%s" % (commit1, commit1)).readlines() + diff2 = git_popen(repo2, "diff %s~1..%s" % (commit2, commit2)).readlines() + return diff_compare2(diff1, diff2) + +def raw_subject(str): + strings = ['ALSA:', 'SOUND:', 'ASOC:', '[ALSA]', '[SOUND]', '[ASOC]'] + up = str.upper() + for s in strings: + if up.startswith(s): + return raw_subject(str[len(s):].strip()) + return str -- 2.47.1