subprocesses, stdin/out, ttys, and beating insubordinate processes into the ground
Steve Holden
steve at holdenweb.com
Wed Jun 7 08:30:24 EDT 2006
Jonathan Smith wrote:
> First a bit about what I'm trying to do. I need a function which takes a
> patchfile and patches a source directory. Thats it. However, I need to
> be able to do so no matter what the patchlevel (-px) of the diff is. So,
> my solution is to just try to patch until it works or you try a level
> more than 3. However, if you have a reversed patch, or patch can't find
> the right file, GNU patch tries to ask for input and I don't want that.
> I know that patch will run non-interactively when backgrounded in a
> shell (no controlling tty). This is what I've tried so far:
>
> def patchme(self, provides, f, destDir, patchlevels):
> for patchlevel in patchlevels:
> patchArgs = ['patch', '-d', destDir, '-p%s'%patchlevel, ]
> if self.backup:
> patchArgs.append(['-b', '-z', self.backup])
> if self.extraArgs:
> patchArgs.append(self.extraArgs)
>
> log.info('attempting to patch the source with file %s and
> patchlevel %s' % (f,patchlevel))
> p1 = subprocess.Popen([provides, f],
> stdout=subprocess.PIPE, shell=False)
> p2 = subprocess.Popen(patchArgs, stdin=p1.stdout, shell=False)
> message = p2.communicate()[0] # patch seems to use stdout
> for everything, even errors
>
> if message != None and self.patcherror.search(message):
> os.kill(p2.pid, signal.SIGTERM)
> elif p2.wait():
> log.info('patch did not apply with path level %s' %
> patchlevel)
> print message
> else:
> return
> log.error('could not apply the patch to your build dir')
>
>
> However, I still get an interactive prompt, no matter what I try! Using
> shell=False did not help, nor did trying to kill the pid if python sees
> a line from patch which isn't saying what its patching or giving info on
> a specific hunk. Any suggestions?
>
> -smithj
>
> PS: if you're a maintainer for GNU patch, a --non-interactive would be
> really nice ;-) (and no, -f and -t aren't good enough as they force
> other things that I don't want)
If the technique you want to use doesn't work, it's usually a good idea
to try another technique. Your current approach is pretty dreadful, when
it would be relatively easy to parse the start of the patchfile and
determine the appropriate level (i.e. -p argument) by finding the file
to be patched.
Neither your approach nor my suggested alternative is that good when the
patch is modifying a file whose name appears at several points in the
directory hierarchy (as may be the case with README, for example), so it
might be even better to parse the whole patchfile and ensure that the
level you choose correctly identifies all target files.
regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Love me, love my blog http://holdenweb.blogspot.com
Recent Ramblings http://del.icio.us/steve.holden
More information about the Python-list
mailing list