| # -*- coding: utf-8 -*- |
| # Copyright 2018 The Chromium OS Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| """Utilities to parse and cache git repository logs.""" |
| |
| from __future__ import print_function |
| |
| import base64 |
| |
| import simpledb |
| import utils |
| |
| |
| class Gitcommit(object): |
| """Gitcommit represents a parsed git commit message.""" |
| def __init__(self, commitid, title, body, files=''): |
| self.commitid = commitid |
| self.title = title |
| self.body = body |
| self.files = files.strip() |
| |
| def __repr__(self): |
| return '%s: %s' % (self.commitid, self.title) |
| |
| |
| class Gitlog(object): |
| """Gitlog reads and parses a gitlog into Gitcommit objects.""" |
| def __init__(self, filename, dbname): |
| self.filename = filename |
| self.dbname = dbname |
| self.commits = [] |
| self.contents = open(self.filename).readlines() |
| |
| utils.rmfile_if_exists(self.dbname) |
| self.parse_log() |
| self.db = simpledb.SimpleDB(dbname) |
| |
| def parse_log(self): |
| """Parse the output of 'git log'.""" |
| i = 0 |
| is_commit_start = lambda x: x.startswith('commit') |
| is_merge_commit = lambda x: x.startswith('Merge:') |
| |
| while i < len(self.contents): |
| if is_commit_start(self.contents[i]): |
| if is_merge_commit(self.contents[i+1]): |
| i += 1 |
| continue |
| |
| commitid = self.contents[i].split()[1] |
| |
| i += 4 |
| title = self.contents[i].strip() |
| title = utils.clean_git_title(title) |
| |
| i += 2 |
| body = '' |
| while (i < len(self.contents) and not |
| is_commit_start(self.contents[i])): |
| if not self.contents[i].startswith(' '): |
| i += 1 |
| break |
| body += self.contents[i].strip() + '\n' |
| i += 1 |
| |
| files = '' |
| while (i < len(self.contents) and not |
| is_commit_start(self.contents[i])): |
| if not self.contents[i].strip(): |
| i += 1 |
| continue |
| files += self.contents[i] |
| i += 1 |
| |
| gc = Gitcommit(commitid, title, body, files) |
| self.commits.append(gc) |
| continue |
| i += 1 |
| |
| def save(self): |
| """Saves parsed git commits into a local cache.""" |
| print("Starting to save %d records" % (len(self.commits))) |
| i = 0 |
| self.db.begin() |
| for commit in self.commits: |
| self.db.insert(commitid=commit.commitid, title=commit.title, |
| body=base64.b64encode(commit.body), |
| files=base64.b64encode(commit.files)) |
| i += 1 |
| if i % 100000 == 0: |
| print('---', i) |
| self.db.commit() |
| print('[+] Done writing %d records to "%s"' % (len(self.commits), |
| self.dbname)) |