Title: Architecture --- Structure ========= ~~~ VersionControl +--Hg.php +--Hg | + CommandProxy.php | +--Container | | +--Repository | | | + Branch.php | | | + Tag.php | | | + Exception.php | | | + Revision.php | | | \ Diff.php | | + Abstract.php | | + Interface.php | | + Bundle.php | | +--Bundle | | | \ Exception.php | | + Repository.php | | + WorkingCopy.php | | \--WorkingCopy | | + Exception.php | | + File.php | | \ Directory.php | +--Command | | + Revert.php | | + Exception.php | | + Backout.php | | + Pull.php | | + Interface.php | | + Abstract.php | | + Push.php | | +--Output | | | \ Formatter.php | | + Branch.php | | + Tag.php | | + Status.php | | + Patch.php | | + Bundle.php | | + Init.php | | + Archive.php | | + Version.php | | + Add.php | | + Copy.php | | + Cat.php | | + Export.php | | + Import.php | | + Log.php | | + Commit.php | | + Forget.php | | + Remove.php | | + Clone.php | | \ Diff.php | + Exception.php | + Executable.php | \--Executable | \ Exception.php ~~~ Hg.php contains the base object which populates two child objects: 1. Executable 2. Repository This base class container is passed to classes which implement Mercurial commands to make available their properties. These are primarily the path to the HG executable and the path to the Repository we will operate on. CommanProxy.php implements the Proxy pattern to invoke the classes which implement Mercurial commands. These are all located in the Command sub-directory. The Output sub-directory contains classes which can parse the raw CLI output and reformat it into PHP Arrays, JSON, plain text and perhaps XML if there is an agreed-upon standard for expressing VCS data in an XML language. Containers are objects which store files and version data. A Repository is equivalent to the '.hg' directory. A Bundle is a compressed file containing a series of revisions in Mercurial's internal format. These can be passed around much like patches. Only certain commands may act on a bundle: export, import, log and several others. A 'Patches' container may be implemented in the future. Design Patterns =============== I decided a factory is not appropriate because the commands implement different options as methods and thus will not have the same interface as should be the case for factories according to Gamma, et al (source: http://brian.deshong.net/talks/2009/atlphp/factory_method_pattern/factory_method_pattern.pdf). I struggled with an appropriate interface, first putting the command first and the repository as an independent object. However, I decided to use Hg.php as the root of all; implement modifiers and options as methods. For example, instead of $repo->status('modified')->excluding('**.bak') I decided to move excluding from Command.php to Repository.php I also coded first with the names of the objects without Hg_Command_Status for example, which is the preferred PEAR way.