Skip to content

Commit

Permalink
Finished release 1.4.8 (merge into master)
Browse files Browse the repository at this point in the history
  • Loading branch information
tchap committed Sep 29, 2014
2 parents 30a8371 + 5d47498 commit 6ef26cf
Show file tree
Hide file tree
Showing 6 changed files with 143 additions and 23 deletions.
2 changes: 1 addition & 1 deletion gitflow/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
# Distributed under a BSD-like license. For full terms see the file LICENSE.txt
#

VERSION = (1, 4, 7)
VERSION = (1, 4, 8)

__version__ = ".".join(map(str, VERSION[0:3])) + "".join(VERSION[3:])
__author__ = "Ondrej Kupka, Tomas Brambora, Hartmut Goebelm, Vincent Driessen"
Expand Down
91 changes: 90 additions & 1 deletion gitflow/bin/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ def register_parser(cls, parent):
cls.register_list(sub)
cls.register_start(sub)
cls.register_finish(sub)
cls.register_purge(sub)
cls.register_checkout(sub)
cls.register_diff(sub)
cls.register_rebase(sub)
Expand Down Expand Up @@ -354,6 +355,95 @@ def run_finish(args):
# git.push(gitflow.origin_name(), upstream)
#print 'OK'

#- purge
@classmethod
def register_purge(cls, parent):
p = parent.add_parser('purge',
help='Purge accepted feature branches.')
p.set_defaults(func=cls.run_purge)

@staticmethod
def run_purge(args):
gitflow = GitFlow()
git = gitflow.git
mgr = gitflow.managers['feature']
origin_name = gitflow.origin_name()

def prompt_user(question):
return raw_input(question).strip().lower() == 'y'

story_cache = {}
def get_story(story_id):
try:
return story_cache[story_id]
except KeyError:
sys.stdout.write('Fetching story {0} ... '.format(story_id))
sys.stdout.flush()
story = pivotal.Story(story_id)
story_cache[story_id] = story
print('')
return story

def get_confirmed_branch_set(features, markers):
to_delete = set()
# Go through the branches and ask the user.
for branch in features:
story_id = pivotal.get_story_id_from_branch_name('feature', branch)
story = get_story(story_id)
if not story.is_accepted():
continue
if not prompt_user('Delete {0}? [y/N]: '.format(branch)):
continue
to_delete.add(branch)
# Check the associated base markers as well.
base = mgr.base_marker_name(branch)
if base in markers:
to_delete.add(base)
# Check the markers that were potentially left behind.
for base in markers:
if base in to_delete:
continue
story_id = pivotal.get_story_id_from_base_marker(base)
story = get_story(story_id)
if not story.is_accepted():
continue
if not prompt_user('Delete {0} (base marker left behind)? [y/N]: '.format(base)):
continue
to_delete.add(base)
return to_delete

print('---> Local branches')
local_branches = [str(b) for b in mgr.iter()]
local_markers = [str(b) for b in mgr.iter_markers()]
to_delete = get_confirmed_branch_set(local_branches, local_markers)
if len(to_delete) != 0:
print('')
for branch in to_delete:
sys.stdout.write('Deleting {} ... '.format(branch))
sys.stdout.flush()
try:
git.branch('-d', branch)
print('OK')
except Exception as ex:
sys.stderr.write('ERR: ' + str(ex) + '\n')
else:
print('\nNo local branches selected, skipping...')

print('\n---> Remote branches')
remote_branches = [str(b)[len(origin_name)+1:] for b in mgr.iter(remote=True)]
remote_markers = [str(b)[len(origin_name)+1:] for b in mgr.iter_markers(remote=True)]
to_delete = get_confirmed_branch_set(remote_branches, remote_markers)
if len(to_delete) != 0:
to_push = []
for branch in to_delete:
to_push.append(':' + branch)
sys.stdout.write('\nDeleting the selected remote branches (push) ... ')
sys.stdout.flush()
gitflow.origin().push(to_push)
print('OK')
else:
print('\nNo remote branches selected, skipping...')

#- checkout
@classmethod
def register_checkout(cls, parent):
Expand Down Expand Up @@ -830,7 +920,6 @@ def register_track(cls, parent):
p.set_defaults(func=cls.run_track)
p.add_argument('version', action=NotEmpty)


@staticmethod
def run_track(args):
gitflow = GitFlow()
Expand Down
12 changes: 12 additions & 0 deletions gitflow/branches.py
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,18 @@ def base_marker_name(self, feature):

return marker

def iter_markers(self, remote=False):
if remote:
refs = self.gitflow.repo.refs
prefix = self.gitflow.origin_name() + '/base_feature/'
else:
refs = self.gitflow.repo.branches
prefix = 'base_feature/'

for r in refs:
if r.name.startswith(prefix):
yield r


class ReleaseBranchManager(BranchManager):
identifier = 'release'
Expand Down
29 changes: 17 additions & 12 deletions gitflow/pivotal.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ def _get_version_matcher():
def _get_token():
return _gitflow._safe_get('gitflow.pt.token')

def _get_client():
def get_client():
return pt.PivotalClient(token=_gitflow._safe_get('gitflow.pt.token'))

def _get_project_id():
return _gitflow._safe_get('gitflow.pt.projectid')

def _iter_current_stories():
client = _get_client()
def iter_current_stories():
client = get_client()
pid = _get_project_id()
iterations = client.iterations.current(pid)
if 'iterations' not in iterations:
Expand All @@ -48,8 +48,8 @@ def _iter_current_stories():
if s.is_feature() or s.is_bug():
yield s

def _iter_backlog_stories():
client = _get_client()
def iter_backlog_stories():
client = get_client()
pid = _get_project_id()
iterations = client.iterations.backlog(pid)
if 'iterations' not in iterations:
Expand All @@ -60,7 +60,7 @@ def _iter_backlog_stories():
if s.is_feature() or s.is_bug():
yield s

def _iter_stories():
def iter_stories():
# Load the PT include/exclude labels from git config.
# Use string.lower() since PT labels are case insensitive.
include = _gitflow.get('gitflow.pt.includelabel', None)
Expand All @@ -72,21 +72,21 @@ def _iter_stories():
exclude = exclude.lower()
exclude = exclude.split(',')

for s in itertools.chain(_iter_current_stories(), _iter_backlog_stories()):
for s in itertools.chain(iter_current_stories(), iter_backlog_stories()):
if include and not s.is_labeled(include):
continue
if exclude and any([l for l in exclude if s.is_labeled(l)]):
continue
yield s

def list_projects():
projects = _get_client().projects.all()['projects']
projects = get_client().projects.all()['projects']
return [(p['id'], p['name']) for p in projects]

class Story(object):
def __init__(self, story_id, _skip_story_download=False):
self._project_id = _get_project_id()
self._client = _get_client()
self._client = get_client()
if _skip_story_download:
return
payload = self._client.stories.get(self._project_id, story_id)
Expand Down Expand Up @@ -300,7 +300,7 @@ def __init__(self, version, _skip_story_download=False):

if _skip_story_download:
return
self._current_stories = list(_iter_current_stories())
self._current_stories = list(iter_current_stories())

def __iter__(self):
for story in self._current_stories:
Expand Down Expand Up @@ -404,7 +404,7 @@ def dump_stories(self):
@classmethod
def dump_all_releases(cls):
stories = dict()
for story in _iter_current_stories():
for story in iter_current_stories():
if story.is_feature() or story.is_bug():
release = story.get_release()
if release:
Expand Down Expand Up @@ -460,7 +460,7 @@ def prompt_user_to_select_story(match=None):

index = ""
print Style.DIM + "--------- Stories -----------" + Style.RESET_ALL
for story in _iter_stories():
for story in iter_stories():
if story.is_feature() and not story.is_estimated():
continue
# You do not start a story if its branch is present or it is
Expand Down Expand Up @@ -640,6 +640,11 @@ def get_story_id_from_branch_name(identifier, branch_name):
return match.groups()[0]


BASE_MARKER_PREFIX = 'base_feature/'

def get_story_id_from_base_marker(base):
return base[len(BASE_MARKER_PREFIX):]

def show_release_summary(gitflow):
current = get_iterations()[0]
current_stories = [
Expand Down
30 changes: 22 additions & 8 deletions gitflow/review.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,9 +78,21 @@ def get_url(self):

def post(self, story, summary_from_story=True):
assert self._rev_range

def to_unicode(s):
try:
return unicode(s)
except UnicodeDecodeError:
return unicode(s, encoding='utf8')

def to_string(us):
try:
return str(us)
except UnicodeEncodeError:
return us.encode(encoding='utf8')

cmd = ['rbt', 'post',
'--branch', self._branch,
'--revision-range={0[0]}:{0[1]}'.format(self._rev_range)]
'--branch', self._branch]

self._check_for_existing_review()

Expand All @@ -93,8 +105,8 @@ def post(self, story, summary_from_story=True):
"%s%n%n"
"%b",
'{0[0]}...{0[1]}'.format(self._rev_range)]
desc_prefix = '> Story being reviewed: {0}\n'.format(story.get_url())
desc = desc_prefix + '\nCOMMIT LOG\n' + sub.check_output(desc_cmd)
desc_prefix = u'> Story being reviewed: {0}\n'.format(story.get_url())
desc = desc_prefix + u'\nCOMMIT LOG\n' + to_unicode(sub.check_output(desc_cmd))

if summary_from_story:
summary = story.get_name()
Expand All @@ -113,8 +125,8 @@ def post(self, story, summary_from_story=True):
for line in lines:
if line.startswith('> Story being reviewed'):
break
kept_desc.append(line.decode('utf-8'))
desc = u'\n'.join(kept_desc) + u'\n' + desc.decode('utf-8')
kept_desc.append(to_unicode(line))
desc = u'\n'.join(kept_desc) + u'\n' + to_unicode(desc)

if self._rid:
sys.stdout.write('updating %s ... ' % str(self._rid))
Expand All @@ -123,8 +135,10 @@ def post(self, story, summary_from_story=True):
else:
sys.stdout.write('new review ... ')

cmd.append('--summary=' + summary.decode('utf8'))
cmd.append('--description=' + desc.decode('utf8'))
cmd.append(u'--summary=' + to_unicode(summary))
cmd.append(u'--description=' + to_unicode(desc))
cmd.extend([str(rev) for rev in self._rev_range])
cmd = [to_string(itm) for itm in cmd]

p = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE)
(outdata, errdata) = p.communicate()
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
'jenkinsapi==0.2.12',
'poster==0.8.1',
'python-dateutil',
'rbtools==0.5.7',
'rbtools==0.6.2',
'setuptools',
'simplejson==3.1.2',
'xmlbuilder==1.0'
Expand Down

0 comments on commit 6ef26cf

Please sign in to comment.