-
-
Notifications
You must be signed in to change notification settings - Fork 652
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This is a small textfile-backed data structure containing info about a pants run, such as the timestamp, commit sha etc. This supercedes the mostly unused BuildInfo functionality, which was removed, to avoid confusion. Auditors: markcc (sapling split of d74c0960a79c1a60aa9293cf6f627fc5b654f899)
- Loading branch information
Benjy
committed
May 7, 2013
1 parent
8004dc9
commit 6f82710
Showing
3 changed files
with
104 additions
and
45 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import getpass | ||
import os | ||
import re | ||
import socket | ||
import time | ||
|
||
from twitter.common.dirutil import safe_mkdir_for | ||
from twitter.pants import get_scm, get_buildroot | ||
|
||
|
||
class RunInfo(object): | ||
"""A little plaintext file containing very basic info about a pants run. | ||
Can only be appended to, never edited.""" | ||
def __init__(self, info_file): | ||
self._info_file = info_file | ||
safe_mkdir_for(self._info_file) | ||
self._info = {} | ||
if os.path.exists(self._info_file): | ||
with open(self._info_file, 'r') as infile: | ||
info = infile.read() | ||
for m in re.finditer("""^([^:]+):(.*)$""", info, re.MULTILINE): | ||
self._info[m.group(1).strip()] = m.group(2).strip() | ||
|
||
def path(self): | ||
return self._info_file | ||
|
||
def get_info(self, key): | ||
return self._info.get(key, None) | ||
|
||
def __getitem__(self, key): | ||
ret = self.get_info(key) | ||
if ret is None: | ||
raise KeyError(key) | ||
return ret | ||
|
||
def get_as_dict(self): | ||
return self._info.copy() | ||
|
||
def add_info(self, key, val): | ||
self.add_infos((key, val)) | ||
|
||
def add_infos(self, *keyvals): | ||
with open(self._info_file, 'a') as outfile: | ||
for key, val in keyvals: | ||
key = key.strip() | ||
val = val.strip() | ||
if ':' in key: | ||
raise Exception, 'info key must not contain a colon' | ||
outfile.write('%s: %s\n' % (key, val)) | ||
self._info[key] = val | ||
|
||
def add_basic_info(self, run_id, timestamp): | ||
"""A helper function to add basic build info.""" | ||
datetime = time.strftime('%A %b %d, %Y %H:%M:%S', time.localtime(timestamp)) | ||
user = getpass.getuser() | ||
machine = socket.gethostname() | ||
path = get_buildroot() | ||
self.add_infos(('id', run_id), ('timestamp', timestamp), ('datetime', datetime), | ||
('user', user), ('machine', machine), ('path', path)) | ||
|
||
def add_scm_info(self): | ||
"""A helper function to add SCM-related info.""" | ||
scm = get_scm() | ||
if scm: | ||
revision = scm.commit_id | ||
tag = scm.tag_name or 'none' | ||
branch = scm.branch_name or revision | ||
else: | ||
revision, tag, branch = 'none', 'none', 'none' | ||
self.add_infos(('revision', revision), ('tag', tag), ('branch', branch)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import unittest2 as unittest | ||
|
||
from twitter.common.contextutil import temporary_file_path | ||
from twitter.pants.base.run_info import RunInfo | ||
|
||
|
||
class RunInfoTest(unittest.TestCase): | ||
def test_run_info_read(self): | ||
with temporary_file_path() as tmppath: | ||
with open(tmppath, 'w') as tmpfile: | ||
tmpfile.write('foo:bar\n baz :qux quux') | ||
ri = RunInfo(tmppath) | ||
self.assertEquals(ri.path(), tmppath) | ||
|
||
# Test get_info access. | ||
self.assertEquals(ri.get_info('foo'), 'bar') | ||
self.assertEquals(ri.get_info('baz'), 'qux quux') | ||
self.assertIsNone(ri.get_info('nonexistent')) | ||
|
||
# Test dict-like access. | ||
self.assertEquals(ri['foo'], 'bar') | ||
self.assertEquals(ri['baz'], 'qux quux') | ||
|
||
def test_write_run_info(self): | ||
with temporary_file_path() as tmppath: | ||
ri = RunInfo(tmppath) | ||
ri.add_info('key1', 'val1') | ||
ri.add_infos(('key2', ' val2'), (' key3 ', 'val3 ')) | ||
self.assertEquals({'key1': 'val1', 'key2': 'val2', 'key3': 'val3'}, ri.get_as_dict()) | ||
|
||
with open(tmppath, 'r') as tmpfile: | ||
contents = tmpfile.read() | ||
self.assertEquals('key1: val1\nkey2: val2\nkey3: val3\n', contents) |