chiark / gitweb /
Refactor message printing
authorKarl Hasselström <kha@treskal.com>
Mon, 21 May 2007 20:58:39 +0000 (21:58 +0100)
committerCatalin Marinas <catalin.marinas@gmail.com>
Mon, 21 May 2007 20:59:29 +0000 (21:59 +0100)
Feed all those little progress and status messages through a central
place where such things as newlines, indentation, and suppressing
output when not on a TTY can be taken care of once and for all.

This patch takes care of almost, but not quite, all output. The most
notable leftover is the printing of help messages.

Signed-off-by: Karl Hasselström <kha@treskal.com>
33 files changed:
stgit/commands/applied.py
stgit/commands/assimilate.py
stgit/commands/branch.py
stgit/commands/clean.py
stgit/commands/commit.py
stgit/commands/common.py
stgit/commands/delete.py
stgit/commands/diff.py
stgit/commands/export.py
stgit/commands/files.py
stgit/commands/fold.py
stgit/commands/hide.py
stgit/commands/id.py
stgit/commands/imprt.py
stgit/commands/log.py
stgit/commands/mail.py
stgit/commands/patches.py
stgit/commands/pick.py
stgit/commands/pull.py
stgit/commands/push.py
stgit/commands/refresh.py
stgit/commands/rename.py
stgit/commands/series.py
stgit/commands/sync.py
stgit/commands/top.py
stgit/commands/unapplied.py
stgit/commands/uncommit.py
stgit/commands/unhide.py
stgit/git.py
stgit/gitmergeonefile.py
stgit/main.py
stgit/stack.py
stgit/utils.py

index f131d6242fe9d74a58920473229eb4fa1ab86219..0925de0f328b8fc58cd059da46b490f3ee336990 100644 (file)
@@ -47,7 +47,7 @@ def func(parser, options, args):
     applied = crt_series.get_applied()
 
     if options.count:
-        print len(applied)
+        out.stdout(len(applied))
     else:
         for p in applied:
-            print p
+            out.stdout(p)
index a8b3bfecac1539d02c4e7b2dd75e0d086fb5486c..e5ebb5537417efdf1e144046ee28a3ded93ac829 100644 (file)
@@ -42,7 +42,7 @@ def func(parser, options, args):
     """
 
     def nothing_to_do():
-        print 'No commits to assimilate'
+        out.info('No commits to assimilate')
 
     top_patch = crt_series.get_current_patch()
     if not top_patch:
@@ -79,8 +79,8 @@ def func(parser, options, args):
 
     victims.reverse()
     for victim in victims:
-        print ('Creating patch "%s" from commit %s'
-               % (patch2name[victim], victim))
+        out.info('Creating patch "%s" from commit %s'
+                 % (patch2name[victim], victim))
         aname, amail, adate = name_email_date(victim.get_author())
         cname, cmail, cdate = name_email_date(victim.get_committer())
         crt_series.new_patch(
index 5e7b0df40b5b6bded84f348b2ec381ac2abce6c4..07bdca815b2069cce75aa509de9e95fb18f8ed8b 100644 (file)
@@ -83,8 +83,8 @@ def __print_branch(branch_name, length):
         current = '>'
     if branch.get_protected():
         protected = 'p'
-    print current + ' ' + initialized + protected + '\t' + \
-          branch_name.ljust(length) + '  | ' + branch.get_description()
+    out.stdout(current + ' ' + initialized + protected + '\t'
+               + branch_name.ljust(length) + '  | ' + branch.get_description())
 
 def __delete_branch(doomed_name, force = False):
     doomed = stack.Series(doomed_name)
@@ -92,8 +92,7 @@ def __delete_branch(doomed_name, force = False):
     if doomed.get_protected():
         raise CmdException, 'This branch is protected. Delete is not permitted'
 
-    print 'Deleting branch "%s"...' % doomed_name,
-    sys.stdout.flush()
+    out.start('Deleting branch "%s"' % doomed_name)
 
     if __is_current_branch(doomed_name):
         check_local_changes()
@@ -108,7 +107,7 @@ def __delete_branch(doomed_name, force = False):
     if doomed_name != 'master':
         git.delete_branch(doomed_name)
 
-    print 'done'
+    out.done()
 
 def func(parser, options, args):
 
@@ -127,17 +126,20 @@ def func(parser, options, args):
                 if git.rev_parse(args[1]) == git.rev_parse('refs/heads/' + args[1]):
                     # we are for sure referring to a branch
                     parentbranch = 'refs/heads/' + args[1]
-                    print 'Recording "%s" as parent branch.' % parentbranch
+                    out.info('Recording "%s" as parent branch' % parentbranch)
                 elif git.rev_parse(args[1]) and re.search('/', args[1]):
                     # FIXME: should the test be more strict ?
                     parentbranch = args[1]
                 else:
                     # Note: this includes refs to StGIT patches
-                    print 'Don\'t know how to determine parent branch from "%s".' % args[1]
+                    out.info('Don\'t know how to determine parent branch'
+                             ' from "%s"' % args[1])
                     parentbranch = None
             except git.GitException:
-                # should use a more specific exception to catch only non-git refs ?
-                print 'Don\'t know how to determine parent branch from "%s".' % args[1]
+                # should use a more specific exception to catch only
+                # non-git refs ?
+                out.info('Don\'t know how to determine parent branch'
+                         ' from "%s"' % args[1])
                 parentbranch = None
 
             tree_id = git_id(args[1])
@@ -148,9 +150,10 @@ def func(parser, options, args):
         if parentbranch:
             parentremote = git.identify_remote(parentbranch)
             if parentremote:
-                print 'Using "%s" remote to pull parent from.' % parentremote
+                out.info('Using remote "%s" to pull parent from'
+                         % parentremote)
             else:
-                print 'Recording as a local branch.'
+                out.info('Recording as a local branch')
         else:
             # no known parent branch, can't guess the remote
             parentremote = None
@@ -159,7 +162,7 @@ def func(parser, options, args):
                                    parent_remote = parentremote,
                                    parent_branch = parentbranch)
 
-        print 'Branch "%s" created.' % args[0]
+        out.info('Branch "%s" created' % args[0])
         return
 
     elif options.clone:
@@ -176,10 +179,9 @@ def func(parser, options, args):
         check_conflicts()
         check_head_top_equal()
 
-        print 'Cloning current branch to "%s"...' % clone,
-        sys.stdout.flush()
+        out.start('Cloning current branch to "%s"' % clone)
         crt_series.clone(clone)
-        print 'done'
+        out.done()
 
         return
 
@@ -202,12 +204,12 @@ def func(parser, options, args):
         branches.sort()
 
         if branches:
-            print 'Available branches:'
+            out.info('Available branches:')
             max_len = max([len(i) for i in branches])
             for i in branches:
                 __print_branch(i, max_len)
         else:
-            print 'No branches'
+            out.info('No branches')
         return
 
     elif options.protect:
@@ -224,10 +226,9 @@ def func(parser, options, args):
             raise CmdException, 'Branch "%s" is not controlled by StGIT' \
                   % branch_name
 
-        print 'Protecting branch "%s"...' % branch_name,
-        sys.stdout.flush()
+        out.start('Protecting branch "%s"' % branch_name)
         branch.protect()
-        print 'done'
+        out.done()
 
         return
 
@@ -241,7 +242,7 @@ def func(parser, options, args):
 
         stack.Series(args[0]).rename(args[1])
 
-        print 'Renamed branch "%s" as "%s".' % (args[0], args[1])
+        out.info('Renamed branch "%s" to "%s"' % (args[0], args[1]))
 
         return
 
@@ -259,10 +260,9 @@ def func(parser, options, args):
             raise CmdException, 'Branch "%s" is not controlled by StGIT' \
                   % branch_name
 
-        print 'Unprotecting branch "%s"...' % branch_name,
-        sys.stdout.flush()
+        out.info('Unprotecting branch "%s"' % branch_name)
         branch.unprotect()
-        print 'done'
+        out.done()
 
         return
 
@@ -294,12 +294,9 @@ def func(parser, options, args):
         check_conflicts()
         check_head_top_equal()
 
-        print 'Switching to branch "%s"...' % args[0],
-        sys.stdout.flush()
-
+        out.start('Switching to branch "%s"' % args[0])
         git.switch_branch(args[0])
-
-        print 'done'
+        out.done()
         return
 
     # default action: print the current branch
index 8f5c60645678de801b1d21aed3daa62f738637f3..7b57526f0691561c3e30c269f16de946d466aaa4 100644 (file)
@@ -43,14 +43,11 @@ def __delete_empty(patches, applied):
     """
     for p in patches:
         if crt_series.empty_patch(p):
-            print 'Deleting patch "%s"...' % p,
-            sys.stdout.flush()
-
+            out.start('Deleting patch "%s"' % p)
             if applied and crt_series.patch_applied(p):
                 crt_series.pop_patch(p)
             crt_series.delete_patch(p)
-
-            print 'done'
+            out.done()
         elif applied and crt_series.patch_unapplied(p):
             crt_series.push_patch(p)
 
index 8af66514a1837f2da6963287c4f2ad212ba0fadb..2b8d7cefab0bddd98f35de3e4ef8be622c576ba5 100644 (file)
@@ -54,8 +54,7 @@ def func(parser, options, args):
 
     crt_head = git.get_head()
 
-    print 'Committing %d patches...' % len(applied),
-    sys.stdout.flush()
+    out.start('Committing %d patches' % len(applied))
 
     crt_series.pop_patch(applied[0])
     git.switch(crt_head)
@@ -63,4 +62,4 @@ def func(parser, options, args):
     for patch in applied:
         crt_series.delete_patch(patch)
 
-    print 'done'
+    out.done()
index 28026da94ac19aca330fd7a2652ba5761c988553..22c78aec8f5a76850e70aff5c2ba8b646f0a91c0 100644 (file)
@@ -131,9 +131,9 @@ def print_crt_patch(branch = None):
         patch = stack.Series(branch).get_current()
 
     if patch:
-        print 'Now at patch "%s"' % patch
+        out.info('Now at patch "%s"' % patch)
     else:
-        print 'No patches applied'
+        out.info('No patches applied')
 
 def resolved(filename, reset = None):
     if reset:
@@ -163,58 +163,53 @@ def push_patches(patches, check_merged = False):
     """
     forwarded = crt_series.forward_patches(patches)
     if forwarded > 1:
-        print 'Fast-forwarded patches "%s" - "%s"' % (patches[0],
-                                                      patches[forwarded - 1])
+        out.info('Fast-forwarded patches "%s" - "%s"'
+                 % (patches[0], patches[forwarded - 1]))
     elif forwarded == 1:
-        print 'Fast-forwarded patch "%s"' % patches[0]
+        out.info('Fast-forwarded patch "%s"' % patches[0])
 
     names = patches[forwarded:]
 
     # check for patches merged upstream
     if names and check_merged:
-        print 'Checking for patches merged upstream...',
-        sys.stdout.flush()
+        out.start('Checking for patches merged upstream')
 
         merged = crt_series.merged_patches(names)
 
-        print 'done (%d found)' % len(merged)
+        out.done('%d found' % len(merged))
     else:
         merged = []
 
     for p in names:
-        print 'Pushing patch "%s"...' % p,
-        sys.stdout.flush()
+        out.start('Pushing patch "%s"' % p)
 
         if p in merged:
             crt_series.push_patch(p, empty = True)
-            print 'done (merged upstream)'
+            out.done('merged upstream')
         else:
             modified = crt_series.push_patch(p)
 
             if crt_series.empty_patch(p):
-                print 'done (empty patch)'
+                out.done('empty patch')
             elif modified:
-                print 'done (modified)'
+                out.done('modified')
             else:
-                print 'done'
+                out.done()
 
 def pop_patches(patches, keep = False):
     """Pop the patches in the list from the stack. It is assumed that
     the patches are listed in the stack reverse order.
     """
     if len(patches) == 0:
-        print 'nothing to push/pop'
+        out.info('Nothing to push/pop')
     else:
         p = patches[-1]
         if len(patches) == 1:
-            print 'Popping patch "%s"...' % p,
+            out.start('Popping patch "%s"' % p)
         else:
-            print 'Popping "%s" - "%s" patches...' % (patches[0], p),
-        sys.stdout.flush()
-
+            out.start('Popping patches "%s" - "%s"' % (patches[0], p))
         crt_series.pop_patch(p, keep)
-
-        print 'done'
+        out.done()
 
 def parse_patches(patch_args, patch_list, boundary = 0, ordered = False):
     """Parse patch_args list for patch names in patch_list and return
@@ -334,19 +329,18 @@ def prepare_rebase(real_rebase, force=None):
     # pop all patches
     applied = crt_series.get_applied()
     if len(applied) > 0:
-        print 'Popping all applied patches...',
-        sys.stdout.flush()
+        out.start('Popping all applied patches')
         crt_series.pop_patch(applied[0])
-        print 'done'
+        out.done()
     return applied
 
 def rebase(target):
     if target == git.get_head():
-        print 'Already at "%s", no need for rebasing.' % target
+        out.info('Already at "%s", no need for rebasing.' % target)
         return
-    
-    print 'Rebasing to "%s"...' % target
+    out.start('Rebasing to "%s"' % target)
     git.reset(tree_id = git_id(target))
+    out.done()
 
 def post_rebase(applied, nopush, merged):
     # memorize that we rebased to here
index e1a70c93f8f89974699938b0c98d9ba40cbc4af2..a9e2744dab8d35c6ef10db1a60a015a1d8fe5b65 100644 (file)
@@ -74,7 +74,7 @@ def func(parser, options, args):
     # delete the patches
     for patch in applied + patches:
         crt_series.delete_patch(patch)
-        print 'Patch "%s" successfully deleted' % patch
+        out.info('Patch "%s" successfully deleted' % patch)
 
     if not options.branch:
         print_crt_patch()
index d3e119084759110da6aa06586567cd9cba84975a..f56cbebac8c32a03de8421f9a1e1180c5f06fb45 100644 (file)
@@ -80,7 +80,7 @@ def func(parser, options, args):
         rev2 = None
 
     if options.stat:
-        print git.diffstat(args, git_id(rev1), git_id(rev2))
+        out.stdout_raw(git.diffstat(args, git_id(rev1), git_id(rev2)) + '\n')
     else:
         diff_str = git.diff(args, git_id(rev1), git_id(rev2),
                             binary = options.binary)
index 20d8f67a6be453f9656ff0da9a2ea4c21944227b..cafcbe3076d2947ca0d1499945980c09d0d301db 100644 (file)
@@ -79,8 +79,8 @@ def func(parser, options, args):
         dirname = 'patches-%s' % crt_series.get_branch()
 
     if not options.branch and git.local_changes():
-        print 'Warning: local changes in the tree. ' \
-              'You might want to commit them first'
+        out.warn('Local changes in the tree;'
+                 ' you might want to commit them first')
 
     if not options.stdout:
         if not os.path.isdir(dirname):
@@ -166,9 +166,9 @@ def func(parser, options, args):
             f = open(pfile, 'w+')
 
         if options.stdout and num > 1:
-            print '-------------------------------------------------------------------------------'
+            print '-'*79
             print patch.get_name()
-            print '-------------------------------------------------------------------------------'
+            print '-'*79
 
         # write description
         f.write(descr)
index b33bd2ac2c312fa7b18fd0f29d5f311639197d4e..59893d842414ee097ada715e84aa3687aae8fc69 100644 (file)
@@ -57,8 +57,8 @@ def func(parser, options, args):
     rev2 = git_id('%s//top' % patch)
 
     if options.stat:
-        print git.diffstat(rev1 = rev1, rev2 = rev2)
+        out.stdout_raw(git.diffstat(rev1 = rev1, rev2 = rev2) + '\n')
     elif options.bare:
-        print git.barefiles(rev1, rev2)
+        out.stdout_raw(git.barefiles(rev1, rev2) + '\n')
     else:
-        print git.files(rev1, rev2)
+        out.stdout_raw(git.files(rev1, rev2) + '\n')
index e87ded2154558c8d1cdd72c10370c5f05a28ff67..297dfbf962c089ac9da2a010838b9d52e69a4549 100644 (file)
@@ -61,12 +61,11 @@ def func(parser, options, args):
 
     if filename:
         if os.path.exists(filename):
-            print 'Folding patch "%s"...' % filename,
+            out.start('Folding patch "%s"' % filename)
         else:
             raise CmdException, 'No such file: %s' % filename
     else:
-        print 'Folding patch from stdin...',
-    sys.stdout.flush()
+        out.start('Folding patch from stdin')
 
     if options.threeway:
         crt_patch = crt_series.get_patch(current)
@@ -77,4 +76,4 @@ def func(parser, options, args):
     else:
         git.apply_patch(filename = filename)
 
-    print 'done'
+    out.done()
index 9ef948d15c125010828fbc5eb665da1399347ca3..3cb08e89586631f1c65506f16744e1cd6c6e2086 100644 (file)
@@ -46,4 +46,4 @@ def func(parser, options, args):
 
     for patch in patches:
         crt_series.hide_patch(patch)
-        print 'Patch "%s" hidden' % patch
+        out.info('Patch "%s" hidden' % patch)
index 4226adf9be41fcc6d9889046bdc8ce02a416966d..8c717e85ac543efdc4f10ca4690505dc0b8cd755 100644 (file)
@@ -46,4 +46,4 @@ def func(parser, options, args):
     else:
         parser.error('incorrect number of arguments')
 
-    print git_id(id_str)
+    out.stdout(git_id(id_str))
index 6fcdc62ae8de6f96007a1058e722c04910e3d134..0089a8b5976a1b768c2b434f7e37caaf1b277346 100644 (file)
@@ -255,7 +255,7 @@ def __create_patch(filename, message, author_name, author_email,
         raise CmdException, 'No diff found inside the patch'
 
     if options.ignore and patch in crt_series.get_applied():
-        print 'Ignoring already applied patch "%s"' % patch
+        out.info('Ignoring already applied patch "%s"' % patch)
         return
     if options.replace and patch in crt_series.get_unapplied():
         crt_series.delete_patch(patch)
@@ -289,18 +289,14 @@ def __create_patch(filename, message, author_name, author_email,
                          committer_name = committer_name,
                          committer_email = committer_email)
 
-    print 'Importing patch "%s"...' % patch,
-    sys.stdout.flush()
-
+    out.start('Importing patch "%s"' % patch)
     if options.base:
         git.apply_patch(diff = diff, base = git_id(options.base))
     else:
         git.apply_patch(diff = diff)
-
     crt_series.refresh_patch(edit = options.edit,
                              show_patch = options.showpatch)
-
-    print 'done'    
+    out.done()
 
 def __import_file(filename, options, patch = None):
     """Import a patch from a file or standard input
index a21789eb643419d0050d12f06e5f7af01b219907..e3e17f95ce96f6fd1bec77ba6fb049419029edf7 100644 (file)
@@ -70,7 +70,7 @@ def show_log(log, show_patch):
             secs, tz = author_date.split()
             date = '%s %s' % (time.ctime(int(secs)), tz)
 
-            print descr, date
+            out.stdout('%s %s' % (descr, date))
 
         parent = commit.get_parent()
         if parent:
index 2fcaa5f629429f1c1c669682eafbd9056a7ecc12..1ca6ba24ccb3ae18b6a8e668a856c49cbcd25b42 100644 (file)
@@ -500,13 +500,12 @@ def func(parser, options, args):
             ref_id = msg_id
 
         if options.mbox:
-            print msg_string
+            out.stdout_raw(msg_string + '\n')
         else:
-            print 'Sending the cover message...',
-            sys.stdout.flush()
+            out.start('Sending the cover message')
             __send_message(smtpserver, from_addr, to_addr_list, msg_string,
                            sleep, smtpuser, smtppassword)
-            print 'done'
+            out.done()
 
     # send the patches
     if options.template:
@@ -529,10 +528,9 @@ def func(parser, options, args):
             ref_id = msg_id
 
         if options.mbox:
-            print msg_string
+            out.stdout_raw(msg_string + '\n')
         else:
-            print 'Sending patch "%s"...' % p,
-            sys.stdout.flush()
+            out.start('Sending patch "%s"' % p)
             __send_message(smtpserver, from_addr, to_addr_list, msg_string,
                            sleep, smtpuser, smtppassword)
-            print 'done'
+            out.done()
index dcfbd983892878ab945ddfd96c89c123e388ab1b..a8fb00882a3d596d97abadb9420270f017bc9f89 100644 (file)
@@ -75,7 +75,7 @@ def func(parser, options, args):
                                   git.diff(args, patch.get_bottom(),
                                            patch.get_top()))
             else:
-                print patch.get_name()
+                out.stdout(patch.get_name())
 
     if options.diff:
         pager(diff_output)
index ea0756bcad0379b7e7f945e0d3a73ba54f3bc6bf..a47b201c2936fe4ae93c9b8748ccecbfab315935 100644 (file)
@@ -91,33 +91,30 @@ def func(parser, options, args):
         top = parent
 
     if options.fold:
-        print 'Folding commit %s...' % commit_id,
-        sys.stdout.flush()
+        out.start('Folding commit %s' % commit_id)
 
         # try a direct git-apply first
         if not git.apply_diff(bottom, top):
             git.merge(bottom, git.get_head(), top, recursive = True)
 
-        print 'done'
+        out.done()
     elif options.update:
         rev1 = git_id('//bottom')
         rev2 = git_id('//top')
         files = git.barefiles(rev1, rev2).split('\n')
 
-        print 'Updating with commit %s...' % commit_id,
-        sys.stdout.flush()
+        out.start('Updating with commit %s' % commit_id)
 
         if not git.apply_diff(bottom, top, files = files):
             raise CmdException, 'Patch updating failed'
 
-        print 'done'
+        out.done()
     else:
         message = commit.get_log()
         author_name, author_email, author_date = \
                      name_email_date(commit.get_author())
 
-        print 'Importing commit %s...' % commit_id,
-        sys.stdout.flush()
+        out.start('Importing commit %s' % commit_id)
 
         newpatch = crt_series.new_patch(patchname, message = message, can_edit = False,
                                         unapplied = True, bottom = bottom, top = top,
@@ -137,23 +134,23 @@ def func(parser, options, args):
                 refseries = crt_series
             patch = refseries.get_patch(refpatchname)
             if patch.get_log():
-                print"log was %s" % newpatch.get_log()
-                print "setting log to %s\n" %  patch.get_log()
+                out.info("Log was %s" % newpatch.get_log())
+                out.info("Setting log to %s\n" %  patch.get_log())
                 newpatch.set_log(patch.get_log())
-                print"log is now %s" % newpatch.get_log()
+                out.info("Log is now %s" % newpatch.get_log())
             else:
-                print "no log for %s\n" % patchname
+                out.info("No log for %s\n" % patchname)
+
         if not options.unapplied:
             modified = crt_series.push_patch(patchname)
         else:
             modified = False
 
         if crt_series.empty_patch(patchname):
-            print 'done (empty patch)'
+            out.done('empty patch')
         elif modified:
-            print 'done (modified)'
+            out.done('modified')
         else:
-            print 'done'
-        
+            out.done()
+
     print_crt_patch()
index f551b981d1f3d07a442f36322f384a4251cc1978..beaa7b5b666b1c916d51b4acbdbf9baa0b5fdaa6 100644 (file)
@@ -90,10 +90,10 @@ def func(parser, options, args):
 
     # pull the remote changes
     if policy == 'pull':
-        print 'Pulling from "%s"...' % repository
+        out.info('Pulling from "%s"' % repository)
         git.pull(repository)
     elif policy == 'fetch-rebase':
-        print 'Fetching from "%s"...' % repository
+        out.info('Fetching from "%s"' % repository)
         git.fetch(repository)
         rebase(git.fetch_head())
     elif policy == 'rebase':
index a636ad2a6203c3417b7d4195d56c503d51240c82..17b32f67e4ae5bef5b6bffdb2e812a6b02daa862 100644 (file)
@@ -64,13 +64,12 @@ def func(parser, options, args):
         if not patch:
             raise CmdException, 'No patch to undo'
 
-        print 'Undoing the "%s" push...' % patch,
-        sys.stdout.flush()
+        out.start('Undoing push of "%s"' % patch)
         resolved_all()
         if crt_series.undo_push():
-            print 'done'
+            out.done()
         else:
-            print 'done (patch unchanged)'
+            out.done('patch unchanged')
         print_crt_patch()
 
         return
index 4cf09ae610f1b8373f52f5b8efe6cfdfd220aa41..77dcbda43f52ce5a3bc31f039fcccb312895532b 100644 (file)
@@ -98,10 +98,9 @@ def func(parser, options, args):
         check_head_top_equal()
 
     if options.undo:
-        print 'Undoing the "%s" refresh...' % patch,
-        sys.stdout.flush()
+        out.start('Undoing the refresh of "%s"' % patch)
         crt_series.undo_refresh()
-        print 'done'
+        out.done()
         return
 
     if options.author:
@@ -128,8 +127,7 @@ def func(parser, options, args):
             between = applied[:applied.index(patch):-1]
             pop_patches(between, keep = True)
 
-        print 'Refreshing patch "%s"...' % patch,
-        sys.stdout.flush()
+        out.start('Refreshing patch "%s"' % patch)
 
         if autoresolved == 'yes':
             resolved_all()
@@ -145,12 +143,12 @@ def func(parser, options, args):
                                  backup = True, sign_str = sign_str)
 
         if crt_series.empty_patch(patch):
-            print 'done (empty patch)'
+            out.done('empty patch')
         else:
-            print 'done'
+            out.done()
 
         if options.patch:
             between.reverse()
             push_patches(between)
     else:
-        print 'Patch "%s" is already up to date' % patch
+        out.info('Patch "%s" is already up to date' % patch)
index ca799c3a96316663b5f5e57ebb4f0a1e0b2f2030..d6c53be67639628d5bdbe25c2be50ceab9ce14bc 100644 (file)
@@ -38,7 +38,6 @@ def func(parser, options, args):
     if len(args) != 2:
         parser.error('incorrect number of arguments')
 
-    print 'Renaming patch "%s" -> "%s"...' % (args[0], args[1]),
-    sys.stdout.flush()
+    out.start('Renaming patch "%s" to "%s"' % (args[0], args[1]))
     crt_series.rename_patch(args[0], args[1])
-    print 'done'
+    out.done()
index 7777201c2d98abcfc4f8c91c9cd702d5674da263..b699902f8d4020eb964f53aa1a33a2734eae28a1 100644 (file)
@@ -102,11 +102,11 @@ def __print_patch(patch, hidden, branch_str, prefix, empty_prefix, length,
         patch_str = patch_str.ljust(length)
 
     if options.description:
-        print prefix + patch_str + ' | ' + __get_description(patch)
+        out.stdout(prefix + patch_str + ' | ' + __get_description(patch))
     elif options.author:
-        print prefix + patch_str + ' | ' + __get_author(patch)
+        out.stdout(prefix + patch_str + ' | ' + __get_author(patch))
     else:
-        print prefix + patch_str
+        out.stdout(prefix + patch_str)
 
 def func(parser, options, args):
     """Show the patch series
@@ -157,7 +157,7 @@ def func(parser, options, args):
     patches = applied + unapplied
 
     if options.count:
-        print len(patches)
+        out.stdout(len(patches))
         return
 
     if not patches:
index db52bcdb5076a8ff3cccd4fa515aa4e224d959b7..83590610512b09d768648b57c9d8d53f6a62515f 100644 (file)
@@ -74,13 +74,10 @@ def func(parser, options, args):
                   '--undo cannot be specified with --branch or --series'
         __check_all()
 
-        print 'Undoing the "%s" sync...' % crt_series.get_current(),
-        sys.stdout.flush()
-
+        out.start('Undoing the sync of "%s"' % crt_series.get_current())
         crt_series.undo_refresh()
         git.reset()
-
-        print 'done'
+        out.done()
         return
 
     if options.branch:
@@ -147,8 +144,7 @@ def func(parser, options, args):
             del popped[:idx]
 
         # the actual sync
-        print 'Synchronising "%s"...' % p,
-        sys.stdout.flush()
+        out.start('Synchronising "%s"' % p)
 
         patch = crt_series.get_patch(p)
         bottom = patch.get_bottom()
@@ -167,9 +163,9 @@ def func(parser, options, args):
             # backup information was already reset above
             crt_series.refresh_patch(cache_update = False, backup = False,
                                      log = 'sync')
-            print 'done (updated)'
+            out.done('updated')
         else:
-            print 'done'
+            out.done()
 
     # push the remaining patches
     if popped:
index f36a0b066317f60aa576f57e90a5df054d5864ee..7cc92ca35c23dd1e84ac144d356f8568a886dbfc 100644 (file)
@@ -41,6 +41,6 @@ def func(parser, options, args):
 
     name = crt_series.get_current()
     if name:
-        print name
+        out.stdout(name)
     else:
         raise CmdException, 'No patches applied'
index cbac0524e11f6ce8c63009695c91419d4d97e79c..0d330a1d49f903cc491718a6f091f7290dd5d492 100644 (file)
@@ -46,7 +46,7 @@ def func(parser, options, args):
     unapplied = crt_series.get_unapplied()
 
     if options.count:
-        print len(unapplied)
+        out.stdout(len(unapplied))
     else:
         for p in unapplied:
-            print p
+            out.stdout(p)
index d5f64da05cdedfd589708ce0e502336ccc6296ce..f611d293a4ebd89878e39b6434d99f86e099b635 100644 (file)
@@ -99,13 +99,13 @@ def func(parser, options, args):
     commits = []
     next_commit = crt_series.get_base()
     if patch_nr:
-        print 'Uncommitting %d patches...' % patch_nr,
+        out.start('Uncommitting %d patches' % patch_nr)
         for i in xrange(patch_nr):
             commit, commit_id, parent = get_commit(next_commit)
             commits.append((commit, commit_id, parent))
             next_commit = parent
     else:
-        print 'Uncommitting to %s...' % to_commit
+        out.start('Uncommitting to %s' % to_commit)
         while True:
             commit, commit_id, parent = get_commit(next_commit)
             commits.append((commit, commit_id, parent))
@@ -114,7 +114,6 @@ def func(parser, options, args):
             next_commit = parent
         patch_nr = len(commits)
 
-    sys.stdout.flush()
     for (commit, commit_id, parent), patchname in \
         zip(commits, patchnames or [None for i in xrange(len(commits))]):
         author_name, author_email, author_date = \
@@ -127,5 +126,4 @@ def func(parser, options, args):
                              author_email = author_email,
                              author_date = author_date)
 
-
-    print 'done'
+    out.done()
index f2db05f6ac21724b0d26bb148bc2dc2ea52e4638..74e4743e0fc474818b89b35817d657bc2e80c138 100644 (file)
@@ -46,4 +46,4 @@ def func(parser, options, args):
 
     for patch in patches:
         crt_series.unhide_patch(patch)
-        print 'Patch "%s" unhidden' % patch
+        out.info('Patch "%s" unhidden' % patch)
index 86630ce3900af65d130116aaa1532638de5d4cd7..845c712bae1c4a760d43787324af73da99be46be 100644 (file)
@@ -220,9 +220,8 @@ def __tree_status(files = None, tree_id = 'HEAD', unknown = False,
                   noexclude = True, verbose = False):
     """Returns a list of pairs - [status, filename]
     """
-    if verbose and sys.stdout.isatty():
-        print 'Checking for changes in the working directory...',
-        sys.stdout.flush()
+    if verbose:
+        out.start('Checking for changes in the working directory')
 
     refresh_index()
 
@@ -260,8 +259,8 @@ def __tree_status(files = None, tree_id = 'HEAD', unknown = False,
         if fs[1] not in conflicts:
             cache_files.append(fs)
 
-    if verbose and sys.stdout.isatty():
-        print 'done'
+    if verbose:
+        out.done()
 
     return cache_files
 
@@ -449,8 +448,7 @@ def __copy_single(source, target, target2=''):
         for f in [f.strip() for f in realfiles]:
             m = prefix_regexp.match(f)
             if not m:
-                print '"%s" does not match "%s"' % (f, re_string)
-                assert(m)
+                raise Exception, '"%s" does not match "%s"' % (f, re_string)
             newname = target+target2+'/'+m.group(1)
             if not os.path.exists(os.path.dirname(newname)):
                 os.makedirs(os.path.dirname(newname))
@@ -767,9 +765,9 @@ def status(files = None, modified = False, new = False, deleted = False,
         if files and not fs[1] in files:
             continue
         if all:
-            print '%s %s' % (fs[0], fs[1])
+            out.stdout('%s %s' % (fs[0], fs[1]))
         else:
-            print '%s' % fs[1]
+            out.stdout('%s' % fs[1])
 
 def diff(files = None, rev1 = 'HEAD', rev2 = None, out_fd = None,
          binary = False):
@@ -958,7 +956,7 @@ def apply_patch(filename = None, diff = None, base = None,
             f = file('.stgit-failed.patch', 'w+')
             f.write(diff)
             f.close()
-            print >> sys.stderr, 'Diff written to the .stgit-failed.patch file'
+            out.warn('Diff written to the .stgit-failed.patch file')
 
         raise
 
index 6f4c1d756f314e21f10494110b5caae478c1545b..303e5f77e6b55937043ccaafe5e92eb32b77ce0c 100644 (file)
@@ -21,7 +21,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 import sys, os
 from stgit import basedir
 from stgit.config import config, file_extensions, ConfigOption
-from stgit.utils import append_string
+from stgit.utils import append_string, out
 
 
 class GitMergeException(Exception):
@@ -133,8 +133,8 @@ def interactive_merge(filename):
 
     mtime = os.path.getmtime(filename)
 
-    print 'Trying the interractive %s merge' % \
-          (three_way and 'three-way' or 'two-way')
+    out.info('Trying the interactive %s merge'
+             % (three_way and 'three-way' or 'two-way'))
 
     err = os.system(imerger % files_dict)
     if err != 0:
@@ -165,16 +165,15 @@ def merge(orig_hash, file1_hash, file2_hash,
             if file1_hash == file2_hash:
                 if os.system('git-update-index --cacheinfo %s %s %s'
                              % (file1_mode, file1_hash, path)) != 0:
-                    print >> sys.stderr, 'Error: git-update-index failed'
+                    out.error('git-update-index failed')
                     __conflict(path)
                     return 1
                 if os.system('git-checkout-index -u -f -- %s' % path):
-                    print >> sys.stderr, 'Error: git-checkout-index failed'
+                    out.error('git-checkout-index failed')
                     __conflict(path)
                     return 1
                 if file1_mode != file2_mode:
-                    print >> sys.stderr, \
-                          'Error: File added in both, permissions conflict'
+                    out.error('File added in both, permissions conflict')
                     __conflict(path)
                     return 1
             # 3-way merge
@@ -189,9 +188,8 @@ def merge(orig_hash, file1_hash, file2_hash,
                     __remove_files(orig_hash, file1_hash, file2_hash)
                     return 0
                 else:
-                    print >> sys.stderr, \
-                          'Error: three-way merge tool failed for file "%s"' \
-                          % path
+                    out.error('Three-way merge tool failed for file "%s"'
+                              % path)
                     # reset the cache to the first branch
                     os.system('git-update-index --cacheinfo %s %s %s'
                               % (file1_mode, file1_hash, path))
@@ -201,7 +199,7 @@ def merge(orig_hash, file1_hash, file2_hash,
                             interactive_merge(path)
                         except GitMergeException, ex:
                             # interactive merge failed
-                            print >> sys.stderr, str(ex)
+                            out.error(ex)
                             if str(keeporig) != 'yes':
                                 __remove_files(orig_hash, file1_hash,
                                                file2_hash)
@@ -260,23 +258,21 @@ def merge(orig_hash, file1_hash, file2_hash,
             if file1_hash == file2_hash:
                 if os.system('git-update-index --add --cacheinfo %s %s %s'
                              % (file1_mode, file1_hash, path)) != 0:
-                    print >> sys.stderr, 'Error: git-update-index failed'
+                    out.error('git-update-index failed')
                     __conflict(path)
                     return 1
                 if os.system('git-checkout-index -u -f -- %s' % path):
-                    print >> sys.stderr, 'Error: git-checkout-index failed'
+                    out.error('git-checkout-index failed')
                     __conflict(path)
                     return 1
                 if file1_mode != file2_mode:
-                    print >> sys.stderr, \
-                          'Error: File "s" added in both, ' \
-                          'permissions conflict' % path
+                    out.error('File "s" added in both, permissions conflict'
+                              % path)
                     __conflict(path)
                     return 1
             # files added in both but different
             else:
-                print >> sys.stderr, \
-                      'Error: File "%s" added in branches but different' % path
+                out.error('File "%s" added in branches but different' % path)
                 # reset the cache to the first branch
                 os.system('git-update-index --cacheinfo %s %s %s'
                           % (file1_mode, file1_hash, path))
@@ -286,7 +282,7 @@ def merge(orig_hash, file1_hash, file2_hash,
                         interactive_merge(path)
                     except GitMergeException, ex:
                         # interactive merge failed
-                        print >> sys.stderr, str(ex)
+                        out.error(ex)
                         if str(keeporig) != 'yes':
                             __remove_files(orig_hash, file1_hash,
                                            file2_hash)
@@ -312,17 +308,16 @@ def merge(orig_hash, file1_hash, file2_hash,
                 obj = file2_hash
             if os.system('git-update-index --add --cacheinfo %s %s %s'
                          % (mode, obj, path)) != 0:
-                print >> sys.stderr, 'Error: git-update-index failed'
+                out.error('git-update-index failed')
                 __conflict(path)
                 return 1
             __remove_files(orig_hash, file1_hash, file2_hash)
             return os.system('git-checkout-index -u -f -- %s' % path)
 
     # Unhandled case
-    print >> sys.stderr, 'Error: Unhandled merge conflict: ' \
-          '"%s" "%s" "%s" "%s" "%s" "%s" "%s"' \
-          % (orig_hash, file1_hash, file2_hash,
-             path,
-             orig_mode, file1_mode, file2_mode)
+    out.error('Unhandled merge conflict: "%s" "%s" "%s" "%s" "%s" "%s" "%s"'
+              % (orig_hash, file1_hash, file2_hash,
+                 path,
+                 orig_mode, file1_mode, file2_mode))
     __conflict(path)
     return 1
index 1a1f534e310e4423feca92a47bbb1d0c68537d16..eb634b40ccab5f525072f0712d106e89f13b9d46 100644 (file)
@@ -22,6 +22,7 @@ import sys, os
 from optparse import OptionParser
 
 import stgit.commands
+from stgit.utils import out
 
 #
 # The commands map
@@ -36,14 +37,12 @@ class Commands(dict):
         candidates = [cmd for cmd in self.keys() if cmd.startswith(key)]
 
         if not candidates:
-            print >> sys.stderr, 'Unknown command: %s' % key
-            print >> sys.stderr, '  Try "%s help" for a list of ' \
-                  'supported commands' % prog
+            out.error('Unknown command: %s' % key,
+                      'Try "%s help" for a list of supported commands' % prog)
             sys.exit(1)
         elif len(candidates) > 1:
-            print >> sys.stderr, 'Ambiguous command: %s' % key
-            print >> sys.stderr, '  Candidates are: %s' \
-                  % ', '.join(candidates)
+            out.error('Ambiguous command: %s' % key,
+                      'Candidates are: %s' % ', '.join(candidates))
             sys.exit(1)
 
         return candidates[0]
@@ -220,8 +219,7 @@ def main():
         if len(sys.argv) == 3 and not sys.argv[2] in ['-h', '--help']:
             cmd = commands.canonical_cmd(sys.argv[2])
             if not cmd in commands:
-                print >> sys.stderr, '%s help: "%s" command unknown' \
-                      % (prog, cmd)
+                out.error('%s help: "%s" command unknown' % (prog, cmd))
                 sys.exit(1)
 
             sys.argv[0] += ' %s' % cmd
@@ -267,7 +265,7 @@ def main():
     except KeyError:
         debug_level = 0
     except ValueError:
-        print >> sys.stderr, 'Invalid STGIT_DEBUG_LEVEL environment variable'
+        out.error('Invalid STGIT_DEBUG_LEVEL environment variable')
         sys.exit(1)
 
     try:
index cf3b379777691812a947136f5aff05dc6808e130..7a06458aecf164e6ce4eae53612d73f6c10ebc87 100644 (file)
@@ -307,6 +307,7 @@ def update_to_current_format_version(branch, git_dir):
             # The branch doesn't seem to be initialized at all.
             return None
     def set_format_version(v):
+        out.info('Upgraded branch %s to format version %d' % (branch, v))
         config.set(format_version_key(branch), '%d' % v)
     def mkdir(d):
         if not os.path.isdir(d):
@@ -491,10 +492,11 @@ class Series(StgitObject):
         if value:
             return value
         elif 'origin' in git.remotes_list():
-            print 'Notice: no parent remote declared for stack "%s", ' \
-                  'defaulting to "origin". Consider setting "branch.%s.remote" ' \
-                  'and "branch.%s.merge" with "git repo-config".' \
-                  % (self.__name, self.__name, self.__name)
+            out.note(('No parent remote declared for stack "%s",'
+                      ' defaulting to "origin".' % self.__name),
+                     ('Consider setting "branch.%s.remote" and'
+                      ' "branch.%s.merge" with "git repo-config".'
+                      % (self.__name, self.__name)))
             return 'origin'
         else:
             raise StackException, 'Cannot find a parent remote for "%s"' % self.__name
@@ -507,10 +509,10 @@ class Series(StgitObject):
         if value:
             return value
         elif git.rev_parse('heads/origin'):
-            print 'Notice: no parent branch declared for stack "%s", ' \
-                  'defaulting to "heads/origin". Consider setting ' \
-                  '"branch.%s.stgit.parentbranch" with "git repo-config".' \
-                  % (self.__name, self.__name)
+            out.note(('No parent branch declared for stack "%s",'
+                      ' defaulting to "heads/origin".' % self.__name),
+                     ('Consider setting "branch.%s.stgit.parentbranch"'
+                      ' with "git repo-config".' % self.__name))
             return 'heads/origin'
         else:
             raise StackException, 'Cannot find a parent branch for "%s"' % self.__name
@@ -646,10 +648,10 @@ class Series(StgitObject):
                                             author_email = patch.get_authemail(),
                                             author_date = patch.get_authdate())
             if patch.get_log():
-                print "setting log to %s" %  patch.get_log()
+                out.info('Setting log to %s' %  patch.get_log())
                 newpatch.set_log(patch.get_log())
             else:
-                print "no log for %s" % p
+                out.info('No log for %s' % p)
 
         # fast forward the cloned series to self's top
         new_series.forward_patches(applied)
@@ -697,17 +699,18 @@ class Series(StgitObject):
             if not os.listdir(self.__patch_dir):
                 os.rmdir(self.__patch_dir)
             else:
-                print 'Patch directory %s is not empty.' % self.__patch_dir
+                out.warn('Patch directory %s is not empty' % self.__patch_dir)
 
             try:
                 os.removedirs(self._dir())
             except OSError:
-                raise StackException, 'Series directory %s is not empty.' % self._dir()
+                raise StackException('Series directory %s is not empty'
+                                     % self._dir())
 
             try:
                 os.removedirs(self.__refs_dir)
             except OSError:
-                print 'Refs directory %s is not empty.' % self.__refs_dir
+                out.warn('Refs directory %s is not empty' % self.__refs_dir)
 
         # Cleanup parent informations
         # FIXME: should one day make use of git-config --section-remove,
@@ -1046,10 +1049,9 @@ class Series(StgitObject):
                 try:
                     git.merge(bottom, head, top, recursive = True)
                 except git.GitException, ex:
-                    print >> sys.stderr, \
-                          'The merge failed during "push". ' \
-                          'Use "refresh" after fixing the conflicts or ' \
-                          'revert the operation with "push --undo".'
+                    out.error('The merge failed during "push".',
+                              'Use "refresh" after fixing the conflicts or'
+                              ' revert the operation with "push --undo".')
 
         append_string(self.__applied_file, name)
 
index fbfe748c42910ed7e951608efb14fb01c7664dd9..ad9b1f115679f889e1533b9eaf6364aa35a63afb 100644 (file)
@@ -21,6 +21,86 @@ along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 """
 
+class MessagePrinter(object):
+    def __init__(self):
+        class Output(object):
+            def __init__(self, write, flush):
+                self.write = write
+                self.flush = flush
+                self.at_start_of_line = True
+                self.level = 0
+            def new_line(self):
+                """Ensure that we're at the beginning of a line."""
+                if not self.at_start_of_line:
+                    self.write('\n')
+                    self.at_start_of_line = True
+            def single_line(self, msg, print_newline = True,
+                            need_newline = True):
+                """Write a single line. Newline before and after are
+                separately configurable."""
+                if need_newline:
+                    self.new_line()
+                if self.at_start_of_line:
+                    self.write('  '*self.level)
+                self.write(msg)
+                if print_newline:
+                    self.write('\n')
+                    self.at_start_of_line = True
+                else:
+                    self.flush()
+                    self.at_start_of_line = False
+            def tagged_lines(self, tag, lines):
+                tag += ': '
+                for line in lines:
+                    self.single_line(tag + line)
+                    tag = ' '*len(tag)
+            def write_line(self, line):
+                """Write one line of text on a lines of its own, not
+                indented."""
+                self.new_line()
+                self.write('%s\n' % line)
+                self.at_start_of_line = True
+            def write_raw(self, string):
+                """Write an arbitrary string, possibly containing
+                newlines."""
+                self.new_line()
+                self.write(string)
+                self.at_start_of_line = string.endswith('\n')
+        self.__stdout = Output(sys.stdout.write, sys.stdout.flush)
+        if sys.stdout.isatty():
+            self.__out = self.__stdout
+        else:
+            self.__out = Output(lambda msg: None, lambda: None)
+    def stdout(self, line):
+        """Write a line to stdout."""
+        self.__stdout.write_line(line)
+    def stdout_raw(self, string):
+        """Write a string possibly containing newlines to stdout."""
+        self.__stdout.write_raw(string)
+    def info(self, *msgs):
+        for msg in msgs:
+            self.__out.single_line(msg)
+    def note(self, *msgs):
+        self.__out.tagged_lines('Notice', msgs)
+    def warn(self, *msgs):
+        self.__out.tagged_lines('Warning', msgs)
+    def error(self, *msgs):
+        self.__out.tagged_lines('Error', msgs)
+    def start(self, msg):
+        """Start a long-running operation."""
+        self.__out.single_line('%s ... ' % msg, print_newline = False)
+        self.__out.level += 1
+    def done(self, extramsg = None):
+        """Finish long-running operation."""
+        self.__out.level -= 1
+        if extramsg:
+            msg = 'done (%s)' % extramsg
+        else:
+            msg = 'done'
+        self.__out.single_line(msg, need_newline = False)
+
+out = MessagePrinter()
+
 def mkdir_file(filename, mode):
     """Opens filename with the given mode, creating the directory it's
     in if it doesn't already exist."""
@@ -166,12 +246,11 @@ def call_editor(filename):
         editor = 'vi'
     editor += ' %s' % filename
 
-    print 'Invoking the editor: "%s"...' % editor,
-    sys.stdout.flush()
+    out.start('Invoking the editor: "%s"' % editor)
     err = os.system(editor)
     if err:
         raise EditorException, 'editor failed, exit code: %d' % err
-    print 'done'
+    out.done()
 
 def patch_name_from_msg(msg):
     """Return a string to be used as a patch name. This is generated