Skip to content

Commit

Permalink
A RunInfo file.
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 45 deletions.
45 changes: 0 additions & 45 deletions src/python/twitter/pants/base/build_info.py

This file was deleted.

71 changes: 71 additions & 0 deletions src/python/twitter/pants/base/run_info.py
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))
33 changes: 33 additions & 0 deletions tests/python/twitter/pants/base/test_run_info.py
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)

0 comments on commit 6f82710

Please sign in to comment.