These are the patches in my "proposed" branch to be moved into master
once reviewed.
Thanks.
Catalin Marinas (9):
Use the default git colouring scheme rather than specific scripts
Add the log --clear option
Reinstate the --annotate option for refresh
Convert 'unhide' to the lib infrastructure
Convert 'hide' to the lib infrastructure
Convert 'clone' to the use stgit.lib
Do not sleep after the last patch sent by e-mail
Show some progress information when checking for upstream merges.
Show "Pushing <patch>...done" when pushing a patch
contrib/diffcol.sh | 51 ---------------------------------------------
examples/gitconfig | 4 ++--
setup.py | 3 +--
stgit/commands/clone.py | 30 +++++++++++---------------
stgit/commands/common.py | 8 +++++++
stgit/commands/diff.py | 2 ++
stgit/commands/hide.py | 44 +++++++++++++++++++++------------------
stgit/commands/log.py | 9 +++++++-
stgit/commands/mail.py | 15 ++++++++-----
stgit/commands/refresh.py | 13 +++++++++--
stgit/commands/show.py | 1 +
stgit/commands/unhide.py | 39 +++++++++++++++++++---------------
stgit/config.py | 10 ++++-----
stgit/lib/git.py | 4 ++++
stgit/lib/transaction.py | 15 ++++++++-----
15 files changed, 117 insertions(+), 131 deletions(-)
delete mode 100755 contrib/diffcol.sh
--
Catalin
@@ -15,10 +15,11 @@ along with this program; if not, write to the Free SoftwareFoundation,Inc.,59TemplePlace,Suite330,Boston,MA02111-1307USA"""-importsys,os-fromstgit.commands.commonimport*-fromstgit.utilsimport*-fromstgitimportargparse,stack,git+importos+fromstgit.commandsimportcommon+fromstgit.libimportgit,stack+fromstgitimportargparse+fromstgit.outimportouthelp='Make a local clone of a remote repository'kind='repo'
@@ -38,7 +39,7 @@ not already exist."""args=[argparse.repo,argparse.dir]options=[]-directory=DirectoryAnywhere(needs_current_series=False,log=False)+directory=common.DirectoryAnywhere(needs_current_series=False,log=False)deffunc(parser,options,args):"""Clone the <repository> into the local <dir> and initialises the
@@ -51,17 +52,12 @@ def func(parser, options, args):local_dir=args[1]ifos.path.exists(local_dir):-raiseCmdException,'"%s" exists. Remove it first'%local_dir--print'Cloning "%s" into "%s"...'%(repository,local_dir)+raisecommon.CmdException,'"%s" exists. Remove it first'%local_dir+out.start('Cloning "%s" into "%s"'%(repository,local_dir))git.clone(repository,local_dir)os.chdir(local_dir)-git.checkout(tree_id='HEAD')--# be sure to forget any cached value for .git, since we're going-# to work on a brand new repository-basedir.clear_cache()-stack.Series().init()--print'done'+directory=common.DirectoryHasRepositoryLib()+directory.setup()+stack.Stack.initialise(directory.repository)+out.done()
@@ -933,3 +933,7 @@ def diffstat(diff):"""Return the diffstat of the supplied diff."""returnrun.Run('git','apply','--stat','--summary').raw_input(diff).raw_output()++defclone(remote,local):+"""Clone a remote repository using 'git clone'."""+run.Run('git','clone',remote,local).run()
It is sometimes useful to add some notes to the log entry when a patch
was refreshed. This option was dropped when the command was updated to
the new infrastructure as there was no logging support at that time.
The note will be visible with 'stg log {-g,-f}'
Signed-off-by: Catalin Marinas <redacted>
---
stgit/commands/refresh.py | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
@@ -61,6 +61,8 @@ options = [short='Refresh (applied) PATCH instead of the top patch'),opt('-e','--edit',action='store_true',short='Invoke an editor for the patch description'),+opt('-a','--annotate',metavar='NOTE',+short='Annotate the patch log entry')]+(argparse.message_options(save_template=False)+argparse.sign_options()+argparse.author_options())
@@ -200,9 +202,13 @@ def absorb_unapplied(trans, iw, patch_name, temp_name, edit_fun):# leave the temp patch for the user.returnFalse-defabsorb(stack,patch_name,temp_name,edit_fun):+defabsorb(stack,patch_name,temp_name,edit_fun,annotate=None):"""Absorb the temp patch into the target patch."""-trans=transaction.StackTransaction(stack,'refresh')+ifannotate:+log_msg='refresh\n\n'+annotate+else:+log_msg='refresh'+trans=transaction.StackTransaction(stack,log_msg)iw=stack.repository.default_iwf={True:absorb_applied,False:absorb_unapplied}[patch_nameintrans.applied]
This patch adds the mechanism to check if the output is tty for the
diff and show commands and passes the --color option to git if the
color.diff config option is set auto or true. The patch also changes the
default pager to 'less -FRSX' from the diffcol.sh script.
Signed-off-by: Catalin Marinas <redacted>
---
contrib/diffcol.sh | 51 ----------------------------------------------
examples/gitconfig | 4 ++--
setup.py | 3 +--
stgit/commands/common.py | 8 +++++++
stgit/commands/diff.py | 2 ++
stgit/commands/show.py | 1 +
stgit/config.py | 10 +++++----
7 files changed, 19 insertions(+), 60 deletions(-)
delete mode 100755 contrib/diffcol.sh
@@ -42,8 +42,8 @@ #editor = /usr/bin/vi # this value overrides the default PAGER environment variable- #pager = ~/share/stgit/contrib/diffcol.sh- #pager = filterdiff --annotate | colordiff | less -FRX+ #pager = less -FRSX+ #pager = filterdiff --annotate | colordiff | less -FRSX # GIT pull and fetch commands (should take the same arguments as # git fetch or git pull). By default:
@@ -83,6 +83,14 @@ def git_commit(name, repository, branch_name = None):exceptlibgit.RepositoryException:raiseCmdException('%s: Unknown patch or revision name'%name)+defcolor_diff_flags():+"""Return the git flags for coloured diff output if the configuration and+stdoutallows."""+ifsys.stdout.isatty()andconfig.get('color.diff')in['true','auto']:+return['--color']+else:+return[]+defcheck_local_changes():ifgit.local_changes():raiseCmdException('local changes in the tree. Use "refresh" or'
@@ -37,7 +37,8 @@ class GitConfig:'stgit.autoimerge':'no','stgit.keepoptimized':'no','stgit.extensions':'.ancestor .current .patched',-'stgit.shortnr':'5'+'stgit.shortnr':'5',+'stgit.pager':'less -FRSX'}__cache={}
@@ -109,10 +110,9 @@ config=GitConfig()defconfig_setup():globalconfig-# Set the PAGER environment to the config value (if any)-pager=config.get('stgit.pager')-ifpager:-os.environ['PAGER']=pager+# Set the PAGER environment to the config value if not already set+ifnot'PAGER'inos.environ:+os.environ['PAGER']=config.get('stgit.pager')# FIXME: handle EDITOR the same way ?classConfigOption:
This option allows the clearing of the log history which sometimes may
get too large.
Signed-off-by: Catalin Marinas <redacted>
---
stgit/commands/log.py | 9 ++++++++-
1 files changed, 8 insertions(+), 1 deletions(-)
@@ -50,7 +50,9 @@ options = [opt('-f','--full',action='store_true',short='Show the full commit ids'),opt('-g','--graphical',action='store_true',-short='Run gitk instead of printing')]+short='Run gitk instead of printing'),+opt('--clear',action='store_true',+short='Clear the log history')]directory=common.DirectoryHasRepositoryLib()
@@ -76,6 +78,11 @@ def func(parser, options, args):exceptKeyError:out.info('Log is empty')return++ifoptions.clear:+log.delete_log(stack.repository,stack.name)+return+stacklog=log.get_log_entry(stack.repository,logref,logcommit)pathlim=[os.path.join('patches',pn)forpninpatches]
@@ -15,12 +15,10 @@ along with this program; if not, write to the Free SoftwareFoundation,Inc.,59TemplePlace,Suite330,Boston,MA02111-1307USA"""-importsys,os+fromstgit.commandsimportcommon+fromstgit.libimporttransaction+fromstgitimportargparsefromstgit.argparseimportopt-fromstgit.commands.commonimport*-fromstgit.utilsimport*-fromstgit.outimport*-fromstgitimportargparse,stack,githelp='Hide a patch in the series'kind='stack'
@@ -29,25 +27,31 @@ description = """Hidearangeofunappliedpatchessothattheyarenolongershownintheplain'series'commandoutput."""-args=[argparse.patch_range(argparse.applied_patches,-argparse.unapplied_patches)]+args=[argparse.patch_range(argparse.unapplied_patches)]options=[opt('-b','--branch',args=[argparse.stg_branches],short='Use BRANCH instead of the default branch')]-directory=DirectoryHasRepository(log=True)+directory=common.DirectoryHasRepositoryLib()deffunc(parser,options,args):-"""Hide a range of patch in the series-"""-ifargs:-# parsing all the patches for a more meaningful error reporting-all_patches=crt_series.get_applied()+crt_series.get_unapplied() \-+crt_series.get_hidden()-patches=parse_patches(args,all_patches)-else:+"""Hide a range of patch in the series."""+stack=directory.repository.current_stack+trans=transaction.StackTransaction(stack,'hide')++ifnotargs:parser.error('No patches specified')-forpatchinpatches:-crt_series.hide_patch(patch)-out.info('Patch "%s" hidden'%patch)+patches=common.parse_patches(args,trans.all_patches)+forpinpatches:+ifpintrans.applied:+raisecommon.CmdException('Cannot hide applied patch "%s"'%p)+elifpintrans.hidden:+raisecommon.CmdException('Patch "%s" already hidden'%p)++applied=list(trans.applied)+unapplied=[pforpintrans.unappliedifnotpinset(patches)]+hidden=patches+trans.hidden++trans.reorder_patches(applied,unapplied,hidden)+returntrans.run()
My main reason is for the automatic invocation of the interactive merge
when I don't know what patch I have to deal with. The other reasons is
for people working over slow filesystems (NFS) where a three-way merging
may take a significant amount of time.
Signed-off-by: Catalin Marinas <redacted>
---
stgit/lib/transaction.py | 13 +++++++------
1 files changed, 7 insertions(+), 6 deletions(-)
@@ -302,6 +302,7 @@ class StackTransaction(object):"""Attempt to push the named patch. If this results in conflicts,haltsthetransaction.Ifindex+worktreearegiven,spillanyconflictstothem."""+out.start('Pushing patch "%s"'%pn)orig_cd=self.patches[pn].datacd=orig_cd.set_committer(None)oldparent=cd.parent
@@ -330,12 +331,12 @@ class StackTransaction(object):iw.merge(base,ours,theirs,interactive=interactive)tree=iw.index.write_tree()self.__current_tree=tree-s=' (modified)'+s='modified'exceptgit.MergeConflictException,e:tree=oursmerge_conflict=Trueself.__conflicts=e.conflicts-s=' (conflict)'+s='conflict'exceptgit.MergeException,e:self.__halt(str(e))cd=cd.set_tree(tree)
@@ -345,12 +346,12 @@ class StackTransaction(object):self.head=commelse:comm=None-s=' (unmodified)'+s='unmodified'ifalready_merged:-s=' (merged)'+s='merged'elifnotmerge_conflictandcd.is_nochange():-s=' (empty)'-out.info('Pushed %s%s'%(pn,s))+s='empty'+out.done(s)defupdate():ifcomm:self.patches[pn]=comm
@@ -390,6 +390,7 @@ class StackTransaction(object):defcheck_merged(self,patches):"""Return a subset of patches already merged."""+out.start('Checking for patches merged upstream')merged=[]ifself.temp_index_tree!=self.stack.head.data.tree:self.temp_index.read_tree(self.stack.head.data.tree)
@@ -408,4 +409,5 @@ class StackTransaction(object):self.temp_index_tree=Noneexceptgit.MergeException:pass+out.done('%d found'%len(merged))returnmerged
@@ -15,12 +15,10 @@ along with this program; if not, write to the Free SoftwareFoundation,Inc.,59TemplePlace,Suite330,Boston,MA02111-1307USA"""-importsys,os+fromstgit.commandsimportcommon+fromstgit.libimporttransaction+fromstgitimportargparsefromstgit.argparseimportopt-fromstgit.commands.commonimport*-fromstgit.utilsimport*-fromstgit.outimport*-fromstgitimportargparse,stack,githelp='Unhide a hidden patch'kind='stack'
@@ -34,19 +32,24 @@ options = [opt('-b','--branch',args=[argparse.stg_branches],short='Use BRANCH instead of the default branch')]-directory=DirectoryHasRepository(log=True)+directory=common.DirectoryHasRepositoryLib()deffunc(parser,options,args):-"""Unhide a range of patches in the series-"""-ifargs:-# parsing all the patches for a more meaningful error reporting-all_patches=crt_series.get_applied()+crt_series.get_unapplied() \-+crt_series.get_hidden()-patches=parse_patches(args,all_patches)-else:+"""Unhide a range of patch in the series."""+stack=directory.repository.current_stack+trans=transaction.StackTransaction(stack,'hide')++ifnotargs:parser.error('No patches specified')-forpatchinpatches:-crt_series.unhide_patch(patch)-out.info('Patch "%s" unhidden'%patch)+patches=common.parse_patches(args,trans.all_patches)+forpinpatches:+ifnotpintrans.hidden:+raisecommon.CmdException('Patch "%s" not hidden'%p)++applied=list(trans.applied)+unapplied=trans.unapplied+patches+hidden=[pforpintrans.hiddenifnotpinset(patches)]++trans.reorder_patches(applied,unapplied,hidden)+returntrans.run()
@@ -229,8 +229,6 @@ def __send_message(smtpserver, from_addr, to_addr_list, msg,# Use the SMTP server (we have host and port information)__send_message_smtp(smtpserver,from_addr,to_addr_list,msg,smtpuser,smtppassword,use_tls)-# give recipients a chance of receiving patches in the correct order-time.sleep(sleep)def__build_address_headers(msg,options,extra_cc=[]):"""Build the address headers and check existing headers in the
@@ -619,7 +617,8 @@ def func(parser, options, args):else:out.start('Sending the cover message')__send_message(smtpserver,from_addr,to_addr_list,msg_string,-sleep,smtpuser,smtppassword,smtpusetls)+smtpuser,smtppassword,smtpusetls)+time.sleep(sleep)out.done()# send the patches
@@ -650,5 +649,9 @@ def func(parser, options, args):else:out.start('Sending patch "%s"'%p)__send_message(smtpserver,from_addr,to_addr_list,msg_string,-sleep,smtpuser,smtppassword,smtpusetls)+smtpuser,smtppassword,smtpusetls)+# give recipients a chance of receiving related patches in the+# correct order.+ifpatch_nr<total_nr:+time.sleep(sleep)out.done()
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
On 2009-04-28 16:09:40 +0100, Catalin Marinas wrote:
My main reason is for the automatic invocation of the interactive
merge when I don't know what patch I have to deal with. The other
reasons is for people working over slow filesystems (NFS) where a
three-way merging may take a significant amount of time.
I don't see any problems with this.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
This is an improvement.
An somewhat related improvement would be to decouple the mail sending
and interactive editing of cover letter and patch mails -- we don't
really need to wait five seconds before letting the user edit the next
patch! (In fact, we should probably let her edit everything first, and
then ask "Send? Y/N" at the end. Or something. Maybe a menu with
options to edit cover letter, edit patches, send, save to mbox, read
from mbox, and discard. But now we're getting into UI land. And most
of this isn't StGit-specific anyway.)
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
On 2009-04-28 16:09:57 +0100, Catalin Marinas wrote:
The patch also adds the stgit.lib.git.clone() function.
if os.path.exists(local_dir):
- raise CmdException, '"%s" exists. Remove it first' % local_dir
-
- print 'Cloning "%s" into "%s"...' % (repository, local_dir)
+ raise common.CmdException, '"%s" exists. Remove it first' % local_dir
As recommended by PEP 8, consider using the "raise Exc(args)" syntax:
- When raising an exception, use "raise ValueError('message')" instead of
the older form "raise ValueError, 'message'".
The paren-using form is preferred because when the exception arguments
are long or include string formatting, you don't need to use line
continuation characters thanks to the containing parentheses. The older
form will be removed in Python 3000.
+def clone(remote, local):
+ """Clone a remote repository using 'git clone'."""
+ run.Run('git', 'clone', remote, local).run()
You don't capture git's output here, but just let it through. Does
that look good in combination with the enclosing out.start() ...
.done() stuff?
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
Why not simply allow all patches? reorder_patches() below will happily
pop unapplied patches before hiding them IIRC, and for already hidden
patches you could just say "already hidden".
Hmm, but this is for the tab completion, so I guess we'd only want the
applied and unapplied patches here.
+ patches = common.parse_patches(args, trans.all_patches)
+ for p in patches:
+ if p in trans.applied:
+ raise common.CmdException('Cannot hide applied patch "%s"' % p)
+ elif p in trans.hidden:
+ raise common.CmdException('Patch "%s" already hidden' % p)
+
+ applied = list(trans.applied)
+ unapplied = [p for p in trans.unapplied if not p in set(patches)]
+ hidden = patches + trans.hidden
+
+ trans.reorder_patches(applied, unapplied, hidden)
+ return trans.run()
As I said,
* Why not simply allow hiding of applied patches?
* Hiding a hidden patch should probably be a warning (if that), not
an error.
Otherwise it looks good.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
On 2009-04-28 16:10:14 +0100, Catalin Marinas wrote:
It is sometimes useful to add some notes to the log entry when a
patch was refreshed. This option was dropped when the command was
updated to the new infrastructure as there was no logging support at
that time.
It looks like if you get a conflict during the refresh (such as when
doing refresh -p, and we can't reorder the patches) the annotation
will be dropped. That could presumably be fixed by tacking it on to
the log message for the creation of the temp patch as well.
But I don't know if it's that important. I've never felt the need for
this feature myself.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
On 2009-04-28 16:10:20 +0100, Catalin Marinas wrote:
This option allows the clearing of the log history which sometimes
may get too large.
Wow, I didn't realize we already had all the pieces for doing this.
Of course, what we'd _really_ want is to delete the log except for the
last N days, or the last N entries. :-) That's gonna be a bit more
work, though, and this is an excellent step in the right direction.
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
From: Karl Hasselström <hidden> Date: 2016-06-15 22:46:41
On 2009-04-28 16:10:25 +0100, Catalin Marinas wrote:
This patch adds the mechanism to check if the output is tty for the
diff and show commands and passes the --color option to git if the
color.diff config option is set auto or true. The patch also changes
the default pager to 'less -FRSX' from the diffcol.sh script.
Seems like a nice improvement.
+ # Set the PAGER environment to the config value if not already set
+ if not 'PAGER' in os.environ:
+ os.environ['PAGER'] = config.get('stgit.pager')
You can replace these two lines with
os.environ.setdefault('PAGER', config.get('stgit.pager'))
The only downside is that config.get() will be evaluated (and the
result discarded) even if PAGER _is_ set in the environment. But
config.get() should be dirt cheap, because we should be reading in all
the config values at once the first time we need one of them. But as I
recall we don't currently do that, so my one-liner might not be so
clever after all ...
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
This patch adds the mechanism to check if the output is tty for the
diff and show commands and passes the --color option to git if the
color.diff config option is set auto or true. The patch also changes the
default pager to 'less -FRSX' from the diffcol.sh script.
Signed-off-by: Catalin Marinas <redacted>
@@ -83,6 +83,14 @@ def git_commit(name, repository, branch_name = None):exceptlibgit.RepositoryException:raiseCmdException('%s: Unknown patch or revision name'%name)+defcolor_diff_flags():+"""Return the git flags for coloured diff output if the configuration and+stdoutallows."""+ifsys.stdout.isatty()andconfig.get('color.diff')in['true','auto']:+return['--color']+else:+return[]+defcheck_local_changes():ifgit.local_changes():raiseCmdException('local changes in the tree. Use "refresh" or'
Junio introduces `color.ui=auto' as one of base settings in his recent
Japanese article for Git newbies:
http://gitster.livejournal.com/2009/04/24/
Is color.ui worth supporting in color_diff_flags()?, or simply having
additional color.diff would be better?
Why not simply allow all patches? reorder_patches() below will happily
pop unapplied patches before hiding them IIRC, and for already hidden
patches you could just say "already hidden".
Hmm, but this is for the tab completion, so I guess we'd only want the
applied and unapplied patches here.
I fixed that in the proposed branch but I was to slow on sending e-mails.
As I said,
* Why not simply allow hiding of applied patches?
* Hiding a hidden patch should probably be a warning (if that), not
an error.
+def color_diff_flags():
+ """Return the git flags for coloured diff output if the configuration
and
+ stdout allows."""
+ if sys.stdout.isatty() and config.get('color.diff') in ['true',
'auto']:
+ return ['--color']
+ else:
+ return []
+
def check_local_changes():
if git.local_changes():
raise CmdException('local changes in the tree. Use "refresh" or'
Junio introduces `color.ui=auto' as one of base settings in his recent
Japanese article for Git newbies:
That's probably a better option. I changed the patch to this (only
showing the relevant parts):
@@ -97,6 +97,15 @@ def git_commit(name, repository, branch_name = None):exceptlibgit.RepositoryException:raiseCmdException('%s: Unknown patch or revision name'%name)+defcolor_diff_flags():+"""Return the git flags for coloured diff output if the configuration and+stdoutallows."""+stdout_is_tty=(sys.stdout.isatty()and'true')or'false'+ifconfig.get_colorbool('color.diff',stdout_is_tty)=='true':+return['--color']+else:+return[]+defcheck_local_changes():ifgit.local_changes():raiseCmdException('local changes in the tree. Use "refresh" or'---a/stgit/config.py+++b/stgit/config.py
@@ -109,16 +110,18 @@ class GitConfig:ifm:result.append(m.group(1))returnresult++defget_colorbool(self,name,stdout_is_tty):+"""Invoke 'git config --get-colorbool' and return the result."""+returnRun('git','config','--get-colorbool',name,+stdout_is_tty).output_one_line()config=GitConfig()
@@ -97,6 +97,15 @@ def git_commit(name, repository, branch_name = None):exceptlibgit.RepositoryException:raiseCmdException('%s: Unknown patch or revision name'%name)+defcolor_diff_flags():+"""Return the git flags for coloured diff output if the configuration and+stdoutallows."""+stdout_is_tty=(sys.stdout.isatty()and'true')or'false'+ifconfig.get_colorbool('color.diff',stdout_is_tty)=='true':+return['--color']+else:+return[]+defcheck_local_changes():ifgit.local_changes():raiseCmdException('local changes in the tree. Use "refresh" or'---a/stgit/config.py+++b/stgit/config.py
@@ -109,16 +110,18 @@ class GitConfig:ifm:result.append(m.group(1))returnresult++defget_colorbool(self,name,stdout_is_tty):+"""Invoke 'git config --get-colorbool' and return the result."""+returnRun('git','config','--get-colorbool',name,+stdout_is_tty).output_one_line()config=GitConfig()
Proposed branch now works for me only with color.ui=auto.
Thanks!
--
Shinya Kuribayashi