My MovableType installation has close to ten patches applied to it to implement functionality I need or fix bugs that are present. Most of my patches can be found here. The patches work great—until the next version of MovableType is released, at which point you have to reapply them, which is tedious and error prone.
A better way of patching would be to pragmatically apply a patch file for a specific fix. The usual way of applying diff patches doesn’t really work, though, since this would require you to make a new patch file based on a new release—i.e. exactly the type of work that I want to avoid. Most MovableType patches consist of directions to go to a particular file, find a section and either replace it or add some code before or after it. This insulates a patch from other changes that may have been made to the file by MT’s authors.
My approach to patching must satisfy the following criteria:
I have the initial format of the patching files specified and I think it’s fairly simple to write a patch file. The following is the patch file that implements the MTElse Fix For Plugins hack:
@@@ NAME: MTElse Fix For Plugins @@@ VERSION: 1.0 @@@ AUTHOR: Stepan Riha @@@ URL: http://www.nonplus.net/software/mt/MTElseFixForPlugins.htm @@@ DESCRIPTION Enables the MTElse tag to properly work for conditional plugins @@@ SYNTAX: perl @@@ FILE: lib/MT/Builder.pm @@@ START sub build { @@@ FIND my($tokens, $uncompiled); @@@ APPEND my $tokens_else; @@@ FIND $tokens = [ grep $_->[0] ne 'Else', @{ $t->[2] } ]; @@@ APPEND $tokens_else = [ grep $_->[0] eq 'Else', @{ $t->[2] } ]; @@@ FIND $ctx->stash('tokens', $tokens); @@@ APPEND $ctx->stash('tokens_else', $tokens_else); @@@ FILE: lib/MT/Template/Context.pm @@@ START sub add_conditional_tag { @@@ FIND if ($condition->(@_)) { return _hdlr_pass_tokens(@_); } else { return ''; } @@@ REPLACE if ($condition->(@_)) { return _hdlr_pass_tokens(@_); } else { my($ctx, $args, $cond) = @_; return $ctx->stash('builder')->build($ctx, $ctx->stash('tokens_else'), $cond); } @@@ END
After the patch has been applied, the patched sections will look like this, in Builder.pm:
... my($tokens, $uncompiled); #### PATCH MTElse Fix For Plugins BEGIN INSERT my $tokens_else; #### PATCH MTElse Fix For Plugins END INSERT ...
And like this in Context.pm:
sub add_conditional_tag { my $class = shift; my($name, $condition) = @_; $Global_handlers{$name} = { code => sub { #### PATCH MTElse Fix For Plugins BEGIN REMOVE #### if ($condition->(@_)) { #### return _hdlr_pass_tokens(@_); #### } else { #### return ''; #### } #### PATCH MTElse Fix For Plugins END REMOVE #### PATCH MTElse Fix For Plugins BEGIN INSERT if ($condition->(@_)) { return _hdlr_pass_tokens(@_); } else { my($ctx, $args, $cond) = @_; return $ctx->stash('builder')->build($ctx, $ctx->stash('tokens_else'), $cond); } #### PATCH MTElse Fix For Plugins END INSERT }, is_container => 1 }; }
I’m envisioning a patching application that can work either as a CGI or off the command line.
The CGI allows for a nice UI, with previews of how a patch modifies the files—I may incorporate this functionality into MT-Medic. However, the CGI approach introduces the difficulties of having to deal with file permissions. It might deal with this by simply telling the user which files to chmod before applying (or unapplying) a patch, if it notices permission conflicts.
The command line tool shouldn’t have permission problems, but most MT users probably don’t have access to the command line—even if they do, most aren’t comfortable with it.
I got some good feedback (i.e. great idea but why reinvent the diff and patch wheel?) on the MT forum - special thanks to distler. I’ll take a look at what modules are available for implementing this using the diff format and then go that route.
After talking with David and taking a look at the progress of the Plugin Manager, I’ve decided to wait for PM to be released and then to try to incorporate patching functionality into it. It’s the more logical application to deal with that and mt-plugins.org would be the logical repository for contributed patches.
It doesn’t look like much beyond a context diff, but I do see where you’re going with it. This seems like something that would quite well suited to work side-by-side somehow with the Plugin Manager. Heck, I could think of some very good uses for it within the Plugin Manager.
Posted by: David Raynes on June 17, 2003 11:07 AMtexas holdem Hi there, very interesting!
Posted by: texas holdem on March 7, 2006 1:46 AM