Commit 98fc2b9b authored by maruel@chromium.org's avatar maruel@chromium.org

Add support to cache arbitrary file.

Rename repository_root to REPOSITORY_ROOT.

Review URL: http://codereview.chromium.org/115615

git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@16598 0039d316-1c4b-4281-b951-d872f2087c98
parent 374d65e5
...@@ -22,7 +22,7 @@ import xml.dom.minidom ...@@ -22,7 +22,7 @@ import xml.dom.minidom
# gcl now depends on gclient. # gcl now depends on gclient.
import gclient import gclient
__version__ = '1.1' __version__ = '1.1.1'
CODEREVIEW_SETTINGS = { CODEREVIEW_SETTINGS = {
...@@ -34,7 +34,7 @@ CODEREVIEW_SETTINGS = { ...@@ -34,7 +34,7 @@ CODEREVIEW_SETTINGS = {
# globals that store the root of the current repository and the directory where # globals that store the root of the current repository and the directory where
# we store information about changelists. # we store information about changelists.
repository_root = "" REPOSITORY_ROOT = ""
# Filename where we store repository specific information for gcl. # Filename where we store repository specific information for gcl.
CODEREVIEW_SETTINGS_FILE = "codereview.settings" CODEREVIEW_SETTINGS_FILE = "codereview.settings"
...@@ -42,8 +42,8 @@ CODEREVIEW_SETTINGS_FILE = "codereview.settings" ...@@ -42,8 +42,8 @@ CODEREVIEW_SETTINGS_FILE = "codereview.settings"
# Warning message when the change appears to be missing tests. # Warning message when the change appears to be missing tests.
MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!" MISSING_TEST_MSG = "Change contains new or modified methods, but no new tests!"
# Caches whether we read the codereview.settings file yet or not. # Global cache of files cached in GetCacheDir().
read_gcl_info = False FILES_CACHE = {}
### SVN Functions ### SVN Functions
...@@ -91,21 +91,21 @@ def GetRepositoryRoot(): ...@@ -91,21 +91,21 @@ def GetRepositoryRoot():
The directory is returned as an absolute path. The directory is returned as an absolute path.
""" """
global repository_root global REPOSITORY_ROOT
if not repository_root: if not REPOSITORY_ROOT:
infos = gclient.CaptureSVNInfo(os.getcwd(), print_error=False) infos = gclient.CaptureSVNInfo(os.getcwd(), print_error=False)
cur_dir_repo_root = infos.get("Repository Root") cur_dir_repo_root = infos.get("Repository Root")
if not cur_dir_repo_root: if not cur_dir_repo_root:
raise Exception("gcl run outside of repository") raise Exception("gcl run outside of repository")
repository_root = os.getcwd() REPOSITORY_ROOT = os.getcwd()
while True: while True:
parent = os.path.dirname(repository_root) parent = os.path.dirname(REPOSITORY_ROOT)
if (gclient.CaptureSVNInfo(parent, print_error=False).get( if (gclient.CaptureSVNInfo(parent, print_error=False).get(
"Repository Root") != cur_dir_repo_root): "Repository Root") != cur_dir_repo_root):
break break
repository_root = parent REPOSITORY_ROOT = parent
return repository_root return REPOSITORY_ROOT
def GetInfoDir(): def GetInfoDir():
...@@ -118,44 +118,72 @@ def GetChangesDir(): ...@@ -118,44 +118,72 @@ def GetChangesDir():
return os.path.join(GetInfoDir(), 'changes') return os.path.join(GetInfoDir(), 'changes')
def GetCodeReviewSetting(key): def GetCacheDir():
"""Returns a value for the given key for this repository.""" """Returns the directory where gcl change files are stored."""
global read_gcl_info return os.path.join(GetInfoDir(), 'cache')
if not read_gcl_info:
read_gcl_info = True
def GetCachedFile(filename, max_age=60*60*24*3, use_root=False):
"""Retrieves a file from the repository and caches it in GetCacheDir() for
max_age seconds.
use_root: If False, look up the arborescence for the first match, otherwise go
directory to the root repository.
Note: The cache will be inconsistent if the same file is retrieved with both
use_root=True and use_root=False on the same file. Don't be stupid.
"""
global FILES_CACHE
if filename not in FILES_CACHE:
# Don't try to look up twice.
FILES_CACHE[filename] = None
# First we check if we have a cached version. # First we check if we have a cached version.
cached_settings_file = os.path.join(GetInfoDir(), CODEREVIEW_SETTINGS_FILE) cached_file = os.path.join(GetCacheDir(), filename)
if (not os.path.exists(cached_settings_file) or if (not os.path.exists(cached_file) or
os.stat(cached_settings_file).st_mtime > 60*60*24*3): os.stat(cached_file).st_mtime > max_age):
dir_info = gclient.CaptureSVNInfo(".") dir_info = gclient.CaptureSVNInfo(".")
repo_root = dir_info["Repository Root"] repo_root = dir_info["Repository Root"]
url_path = dir_info["URL"] if use_root:
settings = "" url_path = repo_root
else:
url_path = dir_info["URL"]
content = ""
while True: while True:
# Look for the codereview.settings file at the current level. # Look for the codereview.settings file at the current level.
svn_path = url_path + "/" + CODEREVIEW_SETTINGS_FILE svn_path = url_path + "/" + filename
settings, rc = RunShellWithReturnCode(["svn", "cat", svn_path]) content, rc = RunShellWithReturnCode(["svn", "cat", svn_path])
if not rc: if not rc:
# Exit the loop if the file was found. # Exit the loop if the file was found. Override content.
break break
# Make sure to mark settings as empty if not found. # Make sure to mark settings as empty if not found.
settings = "" content = ""
if url_path == repo_root: if url_path == repo_root:
# Reached the root. Abandoning search. # Reached the root. Abandoning search.
break; break
# Go up one level to try again. # Go up one level to try again.
url_path = os.path.dirname(url_path) url_path = os.path.dirname(url_path)
# Write a cached version even if there isn't a file, so we don't try to # Write a cached version even if there isn't a file, so we don't try to
# fetch it each time. # fetch it each time.
WriteFile(cached_settings_file, settings) WriteFile(cached_file, content)
else:
content = ReadFile(cached_settings_file)
# Keep the content cached in memory.
FILES_CACHE[filename] = content
return FILES_CACHE[filename]
output = ReadFile(cached_settings_file)
for line in output.splitlines(): def GetCodeReviewSetting(key):
"""Returns a value for the given key for this repository."""
# Use '__just_initialized' as a flag to determine if the settings were
# already initialized.
global CODEREVIEW_SETTINGS
if '__just_initialized' not in CODEREVIEW_SETTINGS:
for line in GetCachedFile(CODEREVIEW_SETTINGS_FILE).splitlines():
if not line or line.startswith("#"): if not line or line.startswith("#"):
continue continue
k, v = line.split(": ", 1) k, v = line.split(": ", 1)
CODEREVIEW_SETTINGS[k] = v CODEREVIEW_SETTINGS[k] = v
CODEREVIEW_SETTINGS.setdefault('__just_initialized', None)
return CODEREVIEW_SETTINGS.get(key, "") return CODEREVIEW_SETTINGS.get(key, "")
...@@ -1035,6 +1063,8 @@ def main(argv=None): ...@@ -1035,6 +1063,8 @@ def main(argv=None):
file_path = os.path.join(unicode(GetInfoDir()), file) file_path = os.path.join(unicode(GetInfoDir()), file)
if os.path.isfile(file_path) and file != CODEREVIEW_SETTINGS_FILE: if os.path.isfile(file_path) and file != CODEREVIEW_SETTINGS_FILE:
shutil.move(file_path, GetChangesDir()) shutil.move(file_path, GetChangesDir())
if not os.path.exists(GetCacheDir()):
os.mkdir(GetCacheDir())
# Commands that don't require an argument. # Commands that don't require an argument.
command = argv[1] command = argv[1]
......
...@@ -54,19 +54,19 @@ class GclUnittest(GclTestsBase): ...@@ -54,19 +54,19 @@ class GclUnittest(GclTestsBase):
members = [ members = [
'CODEREVIEW_SETTINGS', 'CODEREVIEW_SETTINGS_FILE', 'CPP_EXTENSIONS', 'CODEREVIEW_SETTINGS', 'CODEREVIEW_SETTINGS_FILE', 'CPP_EXTENSIONS',
'Change', 'ChangeInfo', 'Changes', 'Commit', 'DoPresubmitChecks', 'Change', 'ChangeInfo', 'Changes', 'Commit', 'DoPresubmitChecks',
'ErrorExit', 'GenerateChangeName', 'GenerateDiff', 'GetChangesDir', 'ErrorExit', 'FILES_CACHE', 'GenerateChangeName', 'GenerateDiff',
'GetCLs', 'GetCacheDir', 'GetCachedFile', 'GetChangesDir', 'GetCLs',
'GetChangelistInfoFile', 'GetCodeReviewSetting', 'GetEditor', 'GetChangelistInfoFile', 'GetCodeReviewSetting', 'GetEditor',
'GetFilesNotInCL', 'GetInfoDir', 'GetIssueDescription', 'GetFilesNotInCL', 'GetInfoDir', 'GetIssueDescription',
'GetModifiedFiles', 'GetRepositoryRoot', 'GetModifiedFiles', 'GetRepositoryRoot',
'GetSVNFileProperty', 'Help', 'IGNORE_PATHS', 'IsSVNMoved', 'IsTreeOpen', 'GetSVNFileProperty', 'Help', 'IGNORE_PATHS', 'IsSVNMoved', 'IsTreeOpen',
'Lint', 'LoadChangelistInfo', 'LoadChangelistInfoForMultiple', 'Lint', 'LoadChangelistInfo', 'LoadChangelistInfoForMultiple',
'MISSING_TEST_MSG', 'Opened', 'PresubmitCL', 'ReadFile', 'MISSING_TEST_MSG', 'Opened', 'PresubmitCL', 'ReadFile',
'RunShell', 'REPOSITORY_ROOT', 'RunShell',
'RunShellWithReturnCode', 'SEPARATOR', 'SendToRietveld', 'TryChange', 'RunShellWithReturnCode', 'SEPARATOR', 'SendToRietveld', 'TryChange',
'UnknownFiles', 'UploadCL', 'Warn', 'WriteFile', 'UnknownFiles', 'UploadCL', 'Warn', 'WriteFile',
'gclient', 'getpass', 'main', 'os', 'random', 're', 'read_gcl_info', 'gclient', 'getpass', 'main', 'os', 'random', 're',
'repository_root', 'shutil', 'string', 'subprocess', 'sys', 'tempfile', 'shutil', 'string', 'subprocess', 'sys', 'tempfile',
'upload', 'urllib2', 'xml', 'upload', 'urllib2', 'xml',
] ]
# If this test fails, you should add the relevant test. # If this test fails, you should add the relevant test.
...@@ -79,12 +79,12 @@ class GclUnittest(GclTestsBase): ...@@ -79,12 +79,12 @@ class GclUnittest(GclTestsBase):
dummy = StringIO.StringIO() dummy = StringIO.StringIO()
gcl.sys.stdout = dummy gcl.sys.stdout = dummy
gcl.Help() gcl.Help()
self.assertEquals(len(dummy.getvalue()), 1813) self.assertEquals(len(dummy.getvalue()), 1815)
finally: finally:
gcl.sys.stdout = old_stdout gcl.sys.stdout = old_stdout
def testGetRepositoryRootNone(self): def testGetRepositoryRootNone(self):
gcl.repository_root = None gcl.REPOSITORY_ROOT = None
gcl.os.getcwd().AndReturn("/bleh/prout") gcl.os.getcwd().AndReturn("/bleh/prout")
result = { result = {
"Repository Root": "" "Repository Root": ""
...@@ -96,7 +96,7 @@ class GclUnittest(GclTestsBase): ...@@ -96,7 +96,7 @@ class GclUnittest(GclTestsBase):
self.mox.VerifyAll() self.mox.VerifyAll()
def testGetRepositoryRootGood(self): def testGetRepositoryRootGood(self):
gcl.repository_root = None gcl.REPOSITORY_ROOT = None
root_path = os.path.join('bleh', 'prout', 'pouet') root_path = os.path.join('bleh', 'prout', 'pouet')
gcl.os.getcwd().AndReturn(root_path) gcl.os.getcwd().AndReturn(root_path)
result1 = { "Repository Root": "Some root" } result1 = { "Repository Root": "Some root" }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment