def test_header(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) result = util.clitest( args=["new"], stdin="""\ tags qwark Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """, cwd=tmp, allow_stderr=True, ) result.check_stdout("") m = result.check_stderr( re.compile( r""" ^ bugit\ new:\ creating\ ticket\ ([0-9a-f]{40})\ \.\.\.\n bugit\ new:\ saved\n $ """, re.VERBOSE, ) ) ticket = m.group(1) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree(path="", repo=tmp, children=True): yield basename got = list(list_tickets()) eq(got, [ticket]) got = sorted(storage.ls(path=ticket, repo=tmp)) eq( got, sorted( [ "description", # TODO 'tags/reporter:TODO' "tags/qwark", ] ), ) got = storage.get(path=os.path.join(ticket, "description"), repo=tmp) eq( got, """\ Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """, ) got = storage.get(path=os.path.join(ticket, "tags/qwark"), repo=tmp) eq(got, "")
def test_transaction_set_simple(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) orig_head = storage.git_rev_parse( rev='bugit/HEAD', repo=tmp, ) with storage.Transaction(repo=tmp) as t: t.set( 'f3da69cd9eca7a69ed72a4edf2d65c84e83b0411/xyzzy', 'mockdata\n', ) got = storage.get( path='f3da69cd9eca7a69ed72a4edf2d65c84e83b0411/xyzzy', repo=tmp, ) eq(got, 'mockdata\n') parent = storage.git_rev_parse( rev='bugit/HEAD^1', repo=tmp, ) eq(orig_head, parent) merge = storage.git_rev_parse( rev='bugit/HEAD^2', repo=tmp, ) eq(merge, None)
def test_transaction_abort(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( 'f3da69cd9eca7a69ed72a4edf2d65c84e83b0411/xyzzy', 'mockdata\n', ) class MyException(Exception): pass try: with storage.Transaction(repo=tmp) as t: t.set( 'f3da69cd9eca7a69ed72a4edf2d65c84e83b0411/xyzzy', 'newvalue\n', ) raise MyException() except MyException: pass else: raise RuntimeError('Expected MyException') got = storage.get( path='f3da69cd9eca7a69ed72a4edf2d65c84e83b0411/xyzzy', repo=tmp, ) eq(got, 'mockdata\n')
def test_ticket_not_first_arg(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) result = util.clitest( args=[ 'edit', '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', ], stdin="""\ tags foo ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """, cwd=tmp, allow_stderr=True, exit_status=1, ) result.check_stdout('') result.check_stderr("""\ bugit edit: updating ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: ticket header not on first line """) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, ['29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5']) got = sorted(storage.ls( path='29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', repo=tmp, )) eq( got, sorted([ 'description', #TODO 'tags/reporter:TODO' ]), ) got = storage.get( path=os.path.join( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', 'description', ), repo=tmp, ) eq(got, 'old')
def test_simple_stdin_ticketAsArg(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) TICKET = '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5' result = util.clitest( args=[ 'edit', TICKET, ], stdin="""\ nop Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """, cwd=tmp, allow_stderr=True, ) result.check_stdout('') result.check_stderr("""\ bugit edit: updating ticket %s ... bugit edit: saved """ % TICKET) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, [TICKET]) got = sorted(storage.ls( path=TICKET, repo=tmp, )) eq( got, sorted([ 'description', #TODO 'tags/reporter:TODO' ]), ) got = storage.get( path=os.path.join(TICKET, 'description'), repo=tmp, ) eq(got, """\ Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """)
def test_editor_simple(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) class FakeTTYFileDescription(object): def isatty(self): return True FAKE_EDITOR = os.path.join(os.path.dirname(__file__), "editor-append") result = util.clitest( args=["new"], environ=dict(BUGIT_EDITOR=FAKE_EDITOR), stdin=FakeTTYFileDescription(), allow_stderr=True, cwd=tmp ) result.check_stdout("") m = result.check_stderr( re.compile( r""" ^ bugit\ new:\ creating\ ticket\ ([0-9a-f]{40})\ \.\.\.\n bugit\ new:\ saved\n $ """, re.VERBOSE, ) ) ticket = m.group(1) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree(path="", repo=tmp, children=True): yield basename got = list(list_tickets()) eq(got, [ticket]) got = sorted(storage.ls(path=ticket, repo=tmp)) eq( got, sorted( [ "description", # TODO 'tags/reporter:TODO' ] ), ) got = storage.get(path=os.path.join(ticket, "description"), repo=tmp) eq( got, """\ Enter description here, with a short first paragraph. Separate variables from main description with "--". Kilroy was here """, )
def main(appinfo, args): """List tickets matching given criteria""" parser = optparse.OptionParser( usage='%prog list [OPTS] [--] [SEARCH..]', ) parser.add_option( '-v', '--verbose', help='show more information', action='count', ) parser.add_option( '--tag', help='only list tickets having this tag', action='append', ) parser.add_option( '--order', help='sort listing according to criteria', ) parser.add_option( '--hide', metavar='FIELD', help='hide field from listing', ) parser.add_option( '--show', metavar='FIELD', help='show field in listing', ) (options, args) = parser.parse_args(args) if args: raise NotImplementedError( 'TODO Full text search not supported yet.') def list_tickets(): for (mode, type_, object, basename) in storage.git_ls_tree( path='', children=True, ): yield basename for ticket in list_tickets(): number = storage.get(os.path.join(ticket, 'number')) if number is not None: number = number.rstrip() ident = '#%s' % number else: ident = ticket[:7] description = storage.get(os.path.join(ticket, 'description')).rstrip() tags = set(storage.ls(os.path.join(ticket, 'tags'))) if options.tag: must = frozenset(options.tag) if not tags & must: continue tags = tagsort.human_friendly_tagsort(tags) if options.verbose: raise NotImplementedError if options.order: raise NotImplementedError if options.show: raise NotImplementedError if options.hide: raise NotImplementedError (title, description) = util.extract_title(description) print '%(ident)s\t%(title)s' % dict( ident=ident, title=title, ) if tags: print textwrap.fill( ' '.join(tags), initial_indent=' ', subsequent_indent=' ', break_long_words=False, )
def test_editor_no_ticket(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) orig_head = storage.git_rev_parse( rev='bugit/HEAD', repo=tmp, ) TICKET = '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5' class FakeTTYFileDescription(object): def isatty(self): return True FAKE_EDITOR = os.path.join( os.path.dirname(__file__), 'editor-that-does-nothing', ) result = util.clitest( args=[ 'edit', ], environ=dict( BUGIT_EDITOR=FAKE_EDITOR, ), stdin=FakeTTYFileDescription(), exit_status=1, allow_stderr=True, cwd=tmp, ) result.check_stdout('') result.check_stderr("""\ bugit edit: Missing ticket argument for interactive editing """) new_head = storage.git_rev_parse( rev='bugit/HEAD', repo=tmp, ) eq(orig_head, new_head) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, [TICKET]) got = sorted(storage.ls( path=TICKET, repo=tmp, )) eq( got, sorted([ 'description', ]), ) got = storage.get( path=os.path.join(TICKET, 'description'), repo=tmp, ) # without explicit no-edit detection, this gets a newline appended eq(got, 'old')
def test_simple_stdin_ticketInStdin(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) orig_head = storage.git_rev_parse( rev='bugit/HEAD', repo=tmp, ) result = util.clitest( args=[ 'edit', ], stdin="""\ ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """, cwd=tmp, allow_stderr=True, ) result.check_stdout('') result.check_stderr("""\ bugit edit: updating ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: saved """) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, ['29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5']) got = sorted(storage.ls( path='29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', repo=tmp, )) eq( got, sorted([ 'description', #TODO 'tags/reporter:TODO' ]), ) got = storage.get( path=os.path.join( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', 'description', ), repo=tmp, ) eq(got, """\ Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """) process = subprocess.Popen( args=[ 'git', 'cat-file', 'commit', 'bugit/HEAD', ], cwd=tmp, close_fds=True, stdout=subprocess.PIPE, ) got = process.stdout.read() returncode = process.wait() eq(returncode, 0) m = re.match( r""" ^ tree\ [0-9a-f]{40}\n parent\ (?P<parent>[0-9a-f]{40})\n author\ [^\n]+\n committer\ [^\n]+\n \n Edited\ ticket\ (?P<ticket>[0-9a-f]{40})\n $ """, got, re.VERBOSE, ) assert m is not None, 'stdout does not match:\n%s' % got eq(m.group('parent'), orig_head) eq(m.group('ticket'), '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5')
def test_editor_simple(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/xyzzy', 'foo', ) TICKET = '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5' class FakeTTYFileDescription(object): def isatty(self): return True FAKE_EDITOR = os.path.join( os.path.dirname(__file__), 'editor-replace', ) result = util.clitest( args=[ 'edit', TICKET, ], environ=dict( BUGIT_EDITOR=FAKE_EDITOR, ), stdin=FakeTTYFileDescription(), allow_stderr=True, cwd=tmp, ) result.check_stdout('') result.check_stderr("""\ bugit edit: editing ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: replacing ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: saved """) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, [TICKET]) got = sorted(storage.ls( path=TICKET, repo=tmp, )) eq( got, sorted([ 'description', 'xyzzy', ]), ) got = storage.get( path=os.path.join(TICKET, 'description'), repo=tmp, ) # as a side-effect, description got trailing newline eq(got, 'old\n') got = storage.get( path=os.path.join(TICKET, 'xyzzy'), repo=tmp, ) eq(got, 'bar\n')
def test_editor_fail(): tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) TICKET = '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5' class FakeTTYFileDescription(object): def isatty(self): return True FAKE_EDITOR = os.path.join( os.path.dirname(__file__), 'editor-that-fails', ) result = util.clitest( args=[ 'edit', TICKET, ], environ=dict( BUGIT_EDITOR=FAKE_EDITOR, ), stdin=FakeTTYFileDescription(), cwd=tmp, allow_stderr=True, exit_status=1, ) result.check_stdout('') result.check_stderr("""\ bugit edit: editing ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: editor failed with exit status 42 """) #TODO bugit edit: file was not changed, discarding def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, [TICKET]) got = sorted(storage.ls( path=TICKET, repo=tmp, )) eq( got, sorted([ 'description', ]), ) got = storage.get( path=os.path.join(TICKET, 'description'), repo=tmp, ) eq(got, 'old')
def test_update_explicit(): # in --update mode, untouched data persists tmp = util.maketemp() storage.git_init(tmp) storage.init(tmp) with storage.Transaction(repo=tmp) as t: t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/description', 'old', ) t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/kilroy', 'was here\n', ) t.set( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5/tags/got-kilroy', '', ) result = util.clitest( args=[ 'edit', '--update', ], stdin="""\ ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. -- frob=v2.4 """, cwd=tmp, allow_stderr=True, ) result.check_stdout('') result.check_stderr("""\ bugit edit: updating ticket 29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5 ... bugit edit: saved """) def list_tickets(): # TODO share me for (mode, type_, object, basename) in storage.git_ls_tree( path='', repo=tmp, children=True, ): yield basename got = list(list_tickets()) eq(got, ['29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5']) got = sorted(storage.ls( path='29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', repo=tmp, )) eq( got, sorted([ 'description', 'kilroy', 'tags/got-kilroy', 'frob', ]), ) got = storage.get( path=os.path.join( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', 'description', ), repo=tmp, ) eq(got, """\ Frobbing is borked I ran frob and it was supposed to blarb, but it qwarked. """) got = storage.get( path=os.path.join( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', 'kilroy', ), repo=tmp, ) eq(got, 'was here\n') got = storage.get( path=os.path.join( '29d7ae1a7d7cefd4c79d095ac0e47636aa02d4a5', 'frob', ), repo=tmp, ) eq(got, 'v2.4\n')