Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(166)

Side by Side Diff: appengine/findit/util_scripts/git_checkout/local_git_repository.py

Issue 2432113002: [Findit] Add local_git_repository (Closed)
Patch Set: Rebase. Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 # Copyright 2016 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 import logging
6 import os
7 from urlparse import urlparse
8 import subprocess
9 import threading
10
11 from git_checkout import local_git_parsers
12 from lib.gitiles.git_repository import GitRepository
13 import script_util
14
15 _CHANGELOG_FORMAT_STRING = ('commit %H%n'
16 'author %an%n'
17 'author-mail %ae%n'
18 'author-time %ad%n%n'
19 'committer %cn%n'
20 'committer-mail %ce%n'
21 'committer-time %cd%n%n'
22 '--Message start--%n%B%n--Message end--%n')
23 _CHANGELOGS_FORMAT_STRING = ('**Changelog start**%%n%s' %
24 _CHANGELOG_FORMAT_STRING)
25 CHECKOUT_ROOT_DIR = os.path.join(os.path.expanduser('~'), '.local_checkouts')
26
27
28 def ConvertRemoteCommitToLocal(revision):
29 """Converts remote commit from gitile to local git checkout revision."""
30 return 'HEAD' if revision == 'master' else revision
31
32
33 class LocalGitRepository(GitRepository):
34 """Represents local checkout of git repository on chromium host.
35
36 Note, to automatically check out internal repos which you have access to,
37 follow the instructions in 'go/internal-repo-checkout-setup'.
38 """
39 lock = threading.Lock()
40 # Keep track all the updated repos, so every repo only get updated once.
41 _updated_repos = set()
42
43 def __init__(self, repo_url=None):
44 self._host = None
45 self._repo_path = None
46 self._repo_url = None
47 self.repo_url = repo_url
48 self.changelog_parser = local_git_parsers.GitChangeLogParser()
49 self.changelogs_parser = local_git_parsers.GitChangeLogsParser()
50 self.blame_parser = local_git_parsers.GitBlameParser()
51 self.diff_parser = local_git_parsers.GitDiffParser()
52
53 @property
54 def repo_path(self):
55 return self._repo_path
56
57 @property
58 def real_repo_path(self):
59 """Absolute path of the local repository."""
60 return os.path.join(CHECKOUT_ROOT_DIR, self._host, self.repo_path)
61
62 @property
63 def repo_url(self):
64 """Url of remote repository which the local repo checks out from."""
65 return self._repo_url
66
67 @repo_url.setter
68 def repo_url(self, repo_url):
69 if self._repo_url == repo_url:
70 return
71
72 self._repo_url = repo_url
73 if not self._repo_url:
74 return
75
76 parsed_url = urlparse(repo_url)
77 self._host = parsed_url.netloc
78 # Remove the / in the front of path.
79 self._repo_path = parsed_url.path[1:]
80
81 self._CloneOrUpdateRepoIfNeeded()
82
83 def _CloneOrUpdateRepoIfNeeded(self):
84 """Clones repo, or update it if it didn't got updated before."""
85 if self.repo_url in LocalGitRepository._updated_repos:
86 return
87
88 with LocalGitRepository.lock:
89 # Clone the repo if needed.
90 if not os.path.exists(self.real_repo_path):
91 try:
92 subprocess.check_call(['git', 'clone',
93 self.repo_url, self.real_repo_path])
94 except subprocess.CalledProcessError as e: # pragma: no cover.
95 logging.error('Exception while cloning %s: %s', self.repo_url, e)
96 return
97 # Update repo if it's already cloned.
98 else:
99 try:
100 # Disable verbose of cd and git pull.
101 with open(os.devnull, 'w') as null_handle:
102 subprocess.check_call(
103 'cd %s && git pull' % self.real_repo_path,
104 stdout=null_handle, stderr=null_handle, shell=True)
105 except subprocess.CalledProcessError as e: # pragma: no cover.
106 logging.error('Exception while updating %s: %s', self.repo_path, e)
107 return
108
109 LocalGitRepository._updated_repos.add(self.repo_url)
110
111 def _GetFinalCommand(self, command, utc=False):
112 # Change local time to utc time.
113 if utc:
114 command = 'TZ=UTC %s --date=format-local:"%s"' % (
115 command, local_git_parsers.DATETIME_FORMAT)
116 return 'cd %s && %s' % (self.real_repo_path, command)
117
118 def GetChangeLog(self, revision):
119 """Returns the change log of the given revision."""
120 command = ('git log --pretty=format:"%s" --max-count=1 --raw '
121 '--no-abbrev %s' % (_CHANGELOG_FORMAT_STRING,
122 ConvertRemoteCommitToLocal(revision)))
123 output = script_util.GetCommandOutput(self._GetFinalCommand(command, True))
124 return self.changelog_parser(output, self.repo_url)
125
126 def GetChangeLogs(self, start_revision, end_revision): # pylint: disable=W
127 """Returns change log list in (start_revision, end_revision]."""
128 command = ('git log --pretty=format:"%s" --raw --no-abbrev %s' % (
129 _CHANGELOGS_FORMAT_STRING,
130 '%s..%s' % (ConvertRemoteCommitToLocal(start_revision),
131 ConvertRemoteCommitToLocal(end_revision))))
132 output = script_util.GetCommandOutput(self._GetFinalCommand(command, True))
133 return self.changelogs_parser(output, self.repo_url)
134
135 def GetChangeDiff(self, revision, path=None): # pylint: disable=W
136 """Returns the diff of the given revision."""
137 command = ('git log --format="" --max-count=1 %s' %
138 ConvertRemoteCommitToLocal(revision))
139 if path:
140 command += ' -p %s' % path
141 output = script_util.GetCommandOutput(self._GetFinalCommand(command))
142 return self.diff_parser(output)
143
144 def GetBlame(self, path, revision):
145 """Returns blame of the file at ``path`` of the given revision."""
146 command = 'git blame --incremental %s %s' % (
147 path, ConvertRemoteCommitToLocal(revision))
148 output = script_util.GetCommandOutput(self._GetFinalCommand(command))
149 return self.blame_parser(output, path, revision)
150
151 def GetSource(self, path, revision):
152 """Returns source code of the file at ``path`` of the given revision."""
153 # Check whether the requested file exist or not.
154 command = 'git show %s:%s' % (ConvertRemoteCommitToLocal(revision), path)
155 output = script_util.GetCommandOutput(self._GetFinalCommand(command))
156 return output
OLDNEW
« no previous file with comments | « appengine/findit/util_scripts/__init__.py ('k') | appengine/findit/util_scripts/git_checkout/test/local_git_parsers_test.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698