# HG changeset patch # User Dmitriy Morozov <dmitriy@mrzv.org> # Date 1239132919 25200 # Node ID 8b6b282d3ebdf9cc811a8f4b54c0c04c1d265f39 # Parent 6ab60ee8b151f3f5f40c8ef5ba3839e18d4df3e2 Combined iadd and iupdate (#b8ff) + added special "resolved" state diff -r 6ab60ee8b151 -r 8b6b282d3ebd .issues/95536ae767c2743a/new/1208380912.M239768P23014Q3.metatron --- a/.issues/95536ae767c2743a/new/1208380912.M239768P23014Q3.metatron Mon May 26 12:03:34 2008 -0400 +++ b/.issues/95536ae767c2743a/new/1208380912.M239768P23014Q3.metatron Tue Apr 07 12:35:19 2009 -0700 @@ -1,8 +1,9 @@ From: Dmitriy Morozov <morozov@cs.duke.edu> Date: Sat, 29 Dec 2007 02:50:26 -0500 -State: new +State: resolved Subject: attachments in iadd Message-Id: <95536ae767c2743a-0-artemis@metatron> +resolution: fixed Add ability to attach files in iadd command. Perhaps use -a flag for it (allowing multiple attachments). Store as a multipart message. List diff -r 6ab60ee8b151 -r 8b6b282d3ebd .issues/95536ae767c2743a/new/1239132767.M919333P28347Q1.cole --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.issues/95536ae767c2743a/new/1239132767.M919333P28347Q1.cole Tue Apr 07 12:35:19 2009 -0700 @@ -0,0 +1,7 @@ +From: Dmitriy Morozov <dmitriy@mrzv.org> +Date: Tue, 07 Apr 2009 12:32:37 +Subject: Fixed in r4754 +Message-Id: <95536ae767c2743a-b476bd16d5d05a72-artemis@cole> +References: <95536ae767c2743a-0-artemis@metatron> +In-Reply-To: <95536ae767c2743a-0-artemis@metatron> + diff -r 6ab60ee8b151 -r 8b6b282d3ebd .issues/b8ff87c45b490683/new/1208863316.M96041P11774Q1.metatron --- a/.issues/b8ff87c45b490683/new/1208863316.M96041P11774Q1.metatron Mon May 26 12:03:34 2008 -0400 +++ b/.issues/b8ff87c45b490683/new/1208863316.M96041P11774Q1.metatron Tue Apr 07 12:35:19 2009 -0700 @@ -1,7 +1,8 @@ From: Dmitriy Morozov <morozov@cs.duke.edu> Date: Tue, 22 Apr 2008 07:21:36 -State: new +State: resolved Subject: Combine iadd and iupdate Message-Id: <b8ff87c45b490683-0-artemis@metatron> +resolution: fixed Combine iadd and iupdate commands into one diff -r 6ab60ee8b151 -r 8b6b282d3ebd .issues/b8ff87c45b490683/new/1239132808.M682158P28352Q1.cole --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.issues/b8ff87c45b490683/new/1239132808.M682158P28352Q1.cole Tue Apr 07 12:35:19 2009 -0700 @@ -0,0 +1,7 @@ +From: Dmitriy Morozov <dmitriy@mrzv.org> +Date: Tue, 07 Apr 2009 12:33:28 +Subject: changed properties (state=resolved, resolution=fixed) +Message-Id: <b8ff87c45b490683-a9a287e189df887a-artemis@cole> +References: <b8ff87c45b490683-0-artemis@metatron> +In-Reply-To: <b8ff87c45b490683-0-artemis@metatron> + diff -r 6ab60ee8b151 -r 8b6b282d3ebd artemis.py --- a/artemis.py Mon May 26 12:03:34 2008 -0400 +++ b/artemis.py Tue Apr 07 12:35:19 2009 -0700 @@ -1,4 +1,4 @@ -# Author: Dmitriy Morozov <hg@foxcub.org>, 2007 +# Author: Dmitriy Morozov <hg@foxcub.org>, 2007 -- 2009 """A very simple and lightweight issue tracker for Mercurial.""" @@ -15,7 +15,7 @@ from email.mime.text import MIMEText -state = {'new': 'new', 'fixed': 'fixed'} +state = {'new': 'new', 'fixed': ['fixed', 'resolved']} state['default'] = state['new'] issues_dir = ".issues" filter_prefix = ".filter" @@ -59,13 +59,13 @@ property_match = True for property,value in properties: property_match = property_match and (mbox[root][property] == value) - if not show_all and (not properties or not property_match) and (properties or mbox[root]['State'].upper() == state['fixed'].upper()): continue + if not show_all and (not properties or not property_match) and (properties or mbox[root]['State'].upper() in [f.upper() for f in state['fixed']]): continue if match_date and not date_match(util.parsedate(mbox[root]['date'])[0]): continue ui.write("%s (%3d) [%s]: %s\n" % (issue[len(issues_path)+1:], # +1 for trailing / len(mbox)-1, # number of replies (-1 for self) - mbox[root]['State'], + _status_msg(mbox[root]), mbox[root]['Subject'])) @@ -93,13 +93,26 @@ default_issue_text += "Subject: brief description\n\n" default_issue_text += "Detailed description." - issue = ui.edit(default_issue_text, user) - if issue.strip() == '': - ui.warn('Empty issue, ignoring\n') - return - if issue.strip() == default_issue_text: - ui.warn('Unchanged issue text, ignoring\n') - return + # Get properties, and figure out if we need an explicit comment + properties = _get_properties(opts['property']) + no_comment = id and properties and opts['no_property_comment'] + + # Create the text + if not no_comment: + issue = ui.edit(default_issue_text, user) + + if issue.strip() == '': + ui.warn('Empty issue, ignoring\n') + return + if issue.strip() == default_issue_text: + ui.warn('Unchanged issue text, ignoring\n') + return + else: + # Write down a comment about updated properties + properties_subject = ', '.join(['%s=%s' % (property, value) for (property, value) in properties]) + + issue = "From: %s\nDate: %s\nSubject: changed properties (%s)\n" % \ + (user, util.datestr(format = date_format), properties_subject) # Create the message msg = mailbox.MaildirMessage(issue) @@ -117,7 +130,7 @@ # else: issue_fn already set # Add message to the mailbox - mbox = mailbox.Maildir(issue_fn) + mbox = mailbox.Maildir(issue_fn, factory=mailbox.MaildirMessage) keys = _order_keys_date(mbox) mbox.lock() if id and comment >= len(mbox): @@ -125,18 +138,31 @@ if not id: outer.add_header('Message-Id', "<%s-0-artemis@%s>" % (issue_id, socket.gethostname())) + root = 0 else: root = keys[0] outer.add_header('Message-Id', "<%s-%s-artemis@%s>" % (issue_id, _random_id(), socket.gethostname())) outer.add_header('References', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id']) outer.add_header('In-Reply-To', mbox[(comment < len(mbox) and keys[comment]) or root]['Message-Id']) repo.add([issue_fn[(len(repo.root)+1):] + '/new/' + mbox.add(outer)]) # +1 for the trailing / + + # Fix properties in the root message + msg = mbox[root] + if properties: + for property, value in properties: + if property in msg: + msg.replace_header(property, value) + else: + msg.add_header(property, value) + mbox[root] = msg + mbox.close() # If adding issue, add the new mailbox to the repository if not id: ui.status('Added new issue %s\n' % issue_id) - + else: + _show_mbox(ui, mbox, 0) def ishow(ui, repo, id, comment = 0, **opts): """Shows issue ID, or possibly its comment COMMENT""" @@ -181,51 +207,6 @@ counter += 1 -def iupdate(ui, repo, id, **opts): - """Update properties of issue ID""" - - issue, id = _find_issue(ui, repo, id) - if not issue: return - - _create_missing_dirs(os.path.join(repo.root, issues_dir), id) - - properties = _get_properties(opts['property']) - - # Read the issue - mbox = mailbox.Maildir(issue, factory=mailbox.MaildirMessage) - root = _find_root_key(mbox) - msg = mbox[root] - - # Fix the properties - properties_text = '' - for property, value in properties: - if property in msg: - msg.replace_header(property, value) - else: - msg.add_header(property, value) - properties_text += '%s=%s\n' % (property, value) - mbox.lock() - mbox[root] = msg - - # Write down a comment about updated properties - if properties and not opts['no_property_comment']: - user = ui.username() - properties_text = "From: %s\nDate: %s\nSubject: properties changes (%s)\n\n%s" % \ - (user, util.datestr(format = date_format), - _pretty_list(list(set([property for property, value in properties]))), - properties_text) - msg = mailbox.mboxMessage(properties_text) - msg.add_header('Message-Id', "<%s-%s-artemis@%s>" % (id, _random_id(), socket.gethostname())) - msg.add_header('References', mbox[root]['Message-Id']) - msg.add_header('In-Reply-To', mbox[root]['Message-Id']) - #msg.set_from('artemis', True) - repo.add([issue[(len(repo.root)+1):] + '/new/' + mbox.add(msg)]) # +1 for the trailing / - mbox.close() - - # Show updated message - _show_mbox(ui, mbox, 0) - - def _find_issue(ui, repo, id): issues_path = os.path.join(repo.root, issues_dir) if not os.path.exists(issues_path): return False @@ -315,12 +296,6 @@ keys.sort(lambda k1,k2: -(k1 == root) or cmp(util.parsedate(mbox[k1]['date']), util.parsedate(mbox[k2]['date']))) return keys -def _pretty_list(lst): - s = '' - for i in lst: - s += i + ', ' - return s[:-2] - def _random_id(): return "%x" % random.randint(2**63, 2**64-1) @@ -378,6 +353,12 @@ outer.attach(attachment) return outer +def _status_msg(msg): + if msg['State'] == 'resolved': + return 'resolved=' + msg['resolution'] + else: + return msg['State'] + cmdtable = { 'ilist': (ilist, [('a', 'all', False, @@ -389,18 +370,16 @@ _('hg ilist [OPTIONS]')), 'iadd': (iadd, [('a', 'attach', [], - 'attach file(s) (e.g., -a filename1 -a filename2)')], - _('hg iadd [ID] [COMMENT]')), + 'attach file(s) (e.g., -a filename1 -a filename2)'), + ('p', 'property', [], + 'update properties (e.g., -p state=fixed)'), + ('n', 'no-property-comment', None, + 'do not add a comment about changed properties')], + _('hg iadd [OPTIONS] [ID] [COMMENT]')), 'ishow': (ishow, [('a', 'all', None, 'list all comments'), ('x', 'extract', [], 'extract attachments')], _('hg ishow [OPTIONS] ID [COMMENT]')), - 'iupdate': (iupdate, - [('p', 'property', [], - 'update properties (e.g., -p state=fixed)'), - ('n', 'no-property-comment', None, - 'do not add a comment about changed properties')], - _('hg iupdate [OPTIONS] ID')) } # vim: expandtab