diff options
-rw-r--r-- | morphlib/plugins/artifact_inspection_plugin.py | 46 | ||||
-rw-r--r-- | morphlib/plugins/branch_and_merge_plugin.py | 281 | ||||
-rw-r--r-- | morphlib/plugins/build_plugin.py | 23 | ||||
-rw-r--r-- | morphlib/plugins/copy-artifacts_plugin.py | 43 | ||||
-rw-r--r-- | morphlib/plugins/deploy_plugin.py | 159 | ||||
-rw-r--r-- | morphlib/plugins/expand_repo_plugin.py | 24 | ||||
-rw-r--r-- | morphlib/plugins/graphing_plugin.py | 30 | ||||
-rw-r--r-- | morphlib/plugins/show_dependencies_plugin.py | 13 | ||||
-rw-r--r-- | morphlib/plugins/trovectl_plugin.py | 23 | ||||
-rw-r--r-- | morphlib/plugins/update_gits_plugin.py | 17 |
10 files changed, 618 insertions, 41 deletions
diff --git a/morphlib/plugins/artifact_inspection_plugin.py b/morphlib/plugins/artifact_inspection_plugin.py index f3417058..0d850319 100644 --- a/morphlib/plugins/artifact_inspection_plugin.py +++ b/morphlib/plugins/artifact_inspection_plugin.py @@ -257,13 +257,26 @@ class ArtifactInspectionPlugin(cliapp.Plugin): arg_synopsis='ARTIFACT CMD') self.app.add_subcommand('generate-manifest', self.generate_manifest, - arg_synopsis='ROOTFS_ARTIFACT') + arg_synopsis='SYSTEM-ARTIFACT') def disable(self): pass def run_in_artifact(self, args): - '''Run a command inside an extracted/mounted chunk or system.''' + '''Run a command inside an extracted/mounted chunk or system. + + Command line arguments: + + * `ARTIFACT` is a filename for the artifact. + * `CMD` is the command to run. + + run-in-artifact unpacks an artifact, and runs a command in + the temporary directory it was unpacked to. + + The command must be given to Morph as a single argument, so + use shell quoting appropriately. + + ''' if len(args) < 2: raise cliapp.AppException( @@ -279,7 +292,34 @@ class ArtifactInspectionPlugin(cliapp.Plugin): call_in_artifact_directory(self.app, artifact, run_command_in_dir) def generate_manifest(self, args): - '''Generate a content manifest for a system image.''' + '''Generate a content manifest for a system image. + + Command line arguments: + + * `SYSTEM-ARTIFACT` is a filename to the system artifact + (root filesystem) for the built system. + + This command generates a manifest for a built system image. + The manifest includes the constituent artifacts, + a guess at the component version, the exact commit for + the component (commit SHA1, repository URL, git symbolic + ref), and the morphology filename. + + + The manifest includes each constituent artifact, with several + columns of data: + + * 7-char cache key with the artifact kind (system, stratum, chunk), + artifact name, and version (if guessable) added + * the git repository + * the symbolic reference + * a 7-char commit id + + Example: + + morph generate-manifest /src/cache/artifacts/foo-rootfs + + ''' if len(args) != 1: raise cliapp.AppException('morph generate-manifest expects ' diff --git a/morphlib/plugins/branch_and_merge_plugin.py b/morphlib/plugins/branch_and_merge_plugin.py index 230367fb..f25e73e6 100644 --- a/morphlib/plugins/branch_and_merge_plugin.py +++ b/morphlib/plugins/branch_and_merge_plugin.py @@ -68,7 +68,8 @@ class BranchAndMergePlugin(cliapp.Plugin): arg_synopsis='SYSTEM STRATUM [CHUNK]') self.app.add_subcommand('petrify', self.petrify) self.app.add_subcommand('unpetrify', self.unpetrify) - self.app.add_subcommand('tag', self.tag) + self.app.add_subcommand( + 'tag', self.tag, arg_synopsis='TAG-NAME -- [GIT-COMMIT-ARG...]') self.app.add_subcommand('build', self.build, arg_synopsis='SYSTEM') self.app.add_subcommand('status', self.status) @@ -547,7 +548,28 @@ class BranchAndMergePlugin(cliapp.Plugin): return system_key, metadata_cache_id_lookup def init(self, args): - '''Initialize a workspace directory.''' + '''Initialize a workspace directory. + + Command line argument: + + * `DIR` is the directory to use as a workspace, and defaults to + the current directory. + + This creates a workspace, either in the current working directory, + or if `DIR` is given, in that directory. If the directory doesn't + exist, it is created. If it does exist, it must be empty. + + You need to run `morph init` to initialise a workspace, or none + of the other system branching tools will work: they all assume + an existing workspace. Note that a workspace only exists on your + machine, not on the git server. + + Example: + + morph init /src/workspace + cd /src/workspace + + ''' if not args: args = ['.'] @@ -610,7 +632,26 @@ class BranchAndMergePlugin(cliapp.Plugin): @warns_git_identity def branch(self, args): - '''Create a new system branch.''' + '''Create a new system branch. + + Command line arguments: + + * `REPO` is a repository URL. + * `NEW` is the name of the new system branch. + * `OLD` is the point from which to branch, and defaults to `master`. + + This creates a new system branch. It needs to be run in an + existing workspace (see `morph workspace`). It creates a new + git branch in the clone of the repository in the workspace. The + system branch will not be visible on the git server until you + push your changes to the repository. + + Example: + + cd /src/workspace + morph branch baserock:baserock:morphs jrandom/new-feature + + ''' if len(args) not in [2, 3]: raise cliapp.AppException('morph branch needs name of branch ' @@ -631,7 +672,25 @@ class BranchAndMergePlugin(cliapp.Plugin): @warns_git_identity def checkout(self, args): - '''Check out an existing system branch.''' + '''Check out an existing system branch. + + Command line arguments: + + * `REPO` is the URL to the repository to the root repository of + a system branch. + * `BRANCH` is the name of the system branch. + + This will check out an existing system branch to an existing + workspace. You must create the workspace first. This only checks + out the root repository, not the repositories for individual + components. You need to use `morph edit` to check out those. + + Example: + + cd /src/workspace + morph checkout baserock:baserock/morphs master + + ''' if len(args) != 2: raise cliapp.AppException('morph checkout needs a repo and the ' @@ -703,7 +762,65 @@ class BranchAndMergePlugin(cliapp.Plugin): @warns_git_identity def edit(self, args): - '''Edit a component in a system branch.''' + '''Edit or checkout a component in a system branch. + + Command line arguments: + + * `SYSTEM` is the name of a system morphology in the root repository + of the current system branch. + * `STRATUM` is the name of a stratum inside the system. + * `CHUNK` is the name of a chunk inside the stratum. + + This marks the specified stratum or chunk (if given) as being + changed within the system branch, by creating the git branches in + the affected repositories, and changing the relevant morphologies + to point at those branches. It also creates a local clone of + the git repository of the stratum or chunk. + + For example: + + morph edit devel-system-x86-64-generic devel + + The above command will mark the `devel` stratum as being + modified in the current system branch. In this case, the stratum's + morphology is in the same git repository as the system morphology, + so there is no need to create a new git branch. However, the + system morphology is modified to point at the stratum morphology + in the same git branch, rather than the original branch. + + In other words, where the system morphology used to say this: + + morph: devel + repo: baserock:baserock/morphs + ref: master + + The updated system morphology will now say this instead: + + morph: devel + repo: baserock:baserock/morphs + ref: jrandom/new-feature + + (Assuming the system branch is called `jrandom/new-feature`.) + + Another example: + + morph edit devel-system-x86_64-generic devel gcc + + The above command will mark the `gcc` chunk as being edited in + the current system branch. Morph will clone the `gcc` repository + locally, into the current workspace, and create a new (local) + branch named after the system branch. It will also change the + stratum morphology to refer to the new git branch, instead of + whatever branch it was referring to originally. + + If the `gcc` repository already had a git branch named after + the system branch, that is reused. Similarly, if the stratum + morphology was already pointing that that branch, it doesn't + need to be changed again. In that case, the only action Morph + does is to clone the chunk repository locally, and if that was + also done already, Morph does nothing. + + ''' if len(args) not in (2, 3): raise cliapp.AppException( @@ -910,10 +1027,42 @@ class BranchAndMergePlugin(cliapp.Plugin): update_working_tree=True) def petrify(self, args): - '''Convert all chunk refs in a system branch to be fixed SHA1s + '''Convert all chunk refs in a system branch to be fixed SHA1s. + + This modifies all git commit references in system and stratum + morphologies, in the current system branch, to be fixed SHA + commit identifiers, rather than symbolic branch or tag names. + This is useful for making sure none of the components in a system + branch change accidentally. + + Consider the following scenario: + + * The `master` system branch refers to `gcc` using the + `baserock/morph` ref. This is appropriate, since the main line + of development should use the latest curated code. + + * You create a system branch to prepare for a release, called + `TROVE_ID/release/2.0`. The reference to `gcc` is still + `baserock/morph`. + + * You test everything, and make a release. You deploy the release + images onto devices, which get shipped to your customers. + + * A new version GCC is committed to the `baserock/morph` branch. + + * Your release branch suddenly uses a new compiler, which may + or may not work for your particular system at that release. + + To avoid this, you need to _petrify_ all git references + so that they do not change accidentally. If you've tested + your release with the GCC release that is stored in commit + `94c50665324a7aeb32f3096393ec54b2e63bfb28`, then you should + continue to use that version of GCC, regardless of what might + happen in the master system branch. If, and only if, you decide + that a new compiler would be good for your release should you + include it in your release branch. This way, only the things + that you change intentionally change in your release branch. - This isolates the branch from changes made by other developers in the - chunk repositories. ''' # Stratum refs are not petrified, because they must all be edited to @@ -934,7 +1083,11 @@ class BranchAndMergePlugin(cliapp.Plugin): branch, os.environ, None, True) def unpetrify(self, args): - '''Reverse the process of petrification''' + '''Reverse the process of petrification. + + This undoes the changes `morph petrify` did. + + ''' # This function makes no attempt to 'unedit' strata that were branched # solely so they could be petrified. @@ -977,6 +1130,26 @@ class BranchAndMergePlugin(cliapp.Plugin): @warns_git_identity def tag(self, args): + '''Create an annotated Git tag of a petrified system branch. + + Command line arguments: + + * `TAG-NAME` is the name of the Git tag to be created. + * `--` separates the Git arguments and options from the ones + Morph parses for itself. + * `GIT-COMMIT-ARG` is a `git commit` option or argument, + e.g., '-m' or '-F'. These should provide the commit message. + + This command creates an annotated Git tag that points at a commit + where all system and stratum morphologies have been petrified. + The working tree won't be petrified, only the commit. + + Example: + + morph tag release-12.765 -- -m "Release 12.765" + + ''' + if len(args) < 1: raise cliapp.AppException('morph tag expects a tag name') @@ -1344,8 +1517,20 @@ class BranchAndMergePlugin(cliapp.Plugin): def merge(self, args): '''Pull and merge changes from a system branch into the current one. - The remote branch is pulled from the current workspace into the target - repositories (so any local commits are included). + Command line arguments: + + * `BRANCH` is the name of the system branch to merge _from_. + + This merges another system branch into the current one. Morph + will do a `git merge` for each component that has been edited, + and undo any changes to `ref` fields in system and stratum + morphologies that `morph edit` has made. + + You need to be in the _target_ system branch when merging. If + you have two system branches, `TROVE_ID/release/1.2` and + `TROVE_ID/bugfixes/12765`, and want to merge the bug fix branch + into the release branch, you need to first checkout the release + system branch, and then merge the bugfix branch into that. ''' @@ -1478,7 +1663,31 @@ class BranchAndMergePlugin(cliapp.Plugin): raise def build(self, args): - '''Build a system from the current system branch''' + '''Build a system image in the current system branch + + Command line arguments: + + * `SYSTEM` is the name of the system to build. + + This builds a system image, and any of its components that + need building. The system name is the basename of the system + morphology, in the root repository of the current system branch, + without the `.morph` suffix in the filename. + + The location of the resulting system image artifact is printed + at the end of the build output. + + You do not need to commit your changes before building, Morph + does that for you, in a temporary branch for each build. However, + note that Morph does not untracked files to the temporary branch, + only uncommitted changes to files git already knows about. You + need to `git add` and commit each new file yourself. + + Example: + + morph build devel-system-x86_64-generic + + ''' if len(args) != 1: raise cliapp.AppException('morph build expects exactly one ' @@ -1726,7 +1935,17 @@ class BranchAndMergePlugin(cliapp.Plugin): ':%s' % info['build-ref']], cwd=info['dirname']) def status(self, args): - '''Show information about the current system branch or workspace''' + '''Show information about the current system branch or workspace + + This shows the status of every local git repository of the + current system branch. This is similar to running `git status` + in each repository separately, but the output is nicer. + + If run in a Morph workspace, but not in a system branch checkout, + it lists all checked out system branches in the workspace. + + ''' + if len(args) != 0: raise cliapp.AppException('morph status takes no arguments') @@ -1770,11 +1989,30 @@ class BranchAndMergePlugin(cliapp.Plugin): self.app.output.write("\nNo repos have outstanding changes.\n") def foreach(self, args): - '''Run a command in each repository checked out in a system branch + '''Run a command in each repository checked out in a system branch. Use -- before specifying the command to separate its arguments from Morph's own arguments. + Command line arguments: + + * `--` indicates the end of option processing for Morph. + * `COMMAND` is a command to run. + * `ARG` is a command line argument or option to be passed onto + `COMMAND`. + + This runs the given `COMMAND` in each git repository belonging + to the current system branch that exists locally in the current + workspace. This can be a handy way to do the same thing in all + the local git repositories. + + For example: + + morph foreach -- git push + + The above command would push any committed changes in each + repository to the git server. + ''' # For simplicity, this simply iterates repositories in the directory @@ -1807,18 +2045,27 @@ class BranchAndMergePlugin(cliapp.Plugin): 'Command failed at repo %s: %s' % (repo, ' '.join(args))) def workspace(self, args): - '''Find the toplevel directory of the current workspace''' + '''Show the toplevel directory of the current workspace.''' self.app.output.write('%s\n' % self.deduce_workspace()) def show_system_branch(self, args): - '''Print name of current system branch''' + '''Show the name of the current system branch.''' branch, dirname = self.deduce_system_branch() self.app.output.write('%s\n' % branch) def show_branch_root(self, args): - '''Print name of the repository holding the system morphologies''' + '''Show the name of the repository holding the system morphologies. + + This would, for example, write out something like: + + /src/ws/master/baserock:baserock/morphs + + when the master branch of the `baserock:baserock/morphs` + repository is checked out. + + ''' workspace = self.deduce_workspace() system_branch, branch_dir = self.deduce_system_branch() diff --git a/morphlib/plugins/build_plugin.py b/morphlib/plugins/build_plugin.py index 128187cf..e9555888 100644 --- a/morphlib/plugins/build_plugin.py +++ b/morphlib/plugins/build_plugin.py @@ -29,10 +29,27 @@ class BuildPlugin(cliapp.Plugin): pass def build_morphology(self, args): - '''Build a system, outside of a system branch + '''Build a system, outside of a system branch. - Command line arguments are the repository, git ref, - and morphology filename. + Command line arguments: + + * `REPO` is a git repository URL. + * `REF` is a branch or other commit reference in that repository. + * `FILENAME` is a morphology filename at that ref. + + You probably want `morph build` instead. However, in some + cases it is more convenient to not have to create a Morph + workspace and check out the relevant system branch, and only + just run the build. For those times, this command exists. + + This subcommand does not automatically commit changes to a + temporary branch, so you can only build from properly committed + sources that have been pushed to the git server. + + Example: + + morph build-morphology baserock:baserock/morphs \ + master devel-system-x86_64-generic ''' diff --git a/morphlib/plugins/copy-artifacts_plugin.py b/morphlib/plugins/copy-artifacts_plugin.py index ab51e522..577d0ef2 100644 --- a/morphlib/plugins/copy-artifacts_plugin.py +++ b/morphlib/plugins/copy-artifacts_plugin.py @@ -37,16 +37,29 @@ class CopyArtifactsPlugin(cliapp.Plugin): def enable(self): self.app.add_subcommand( 'list-artifacts', self.list_artifacts, - arg_synopsis='SYSTEM') + arg_synopsis='SYSTEM-ARTIFACT') self.app.add_subcommand( 'copy-artifacts', self.copy_artifacts, - arg_synopsis='SYSTEM DESTINATION') + arg_synopsis='SYSTEM-ARTIFACT DESTINATION') def disable(self): pass def list_artifacts(self, args): - '''List every artifact that makes up a system''' + '''List every artifact that makes up a system artifact. + + Command line arguments: + + * `SYSTEM-ARTIFACT` is the filename for a build artifact for + a system (ending in `-rootfs`). + + list-artifacts reads the system artifact and writes out a list + of the filenames, in the local artifact cache, of all the + component artifacts included in the system. It does not include + build-dependencies of the system, unless they're included in + the system. + + ''' if len(args) != 1: raise cliapp.AppException( @@ -59,7 +72,29 @@ class CopyArtifactsPlugin(cliapp.Plugin): self.app.output.write(artifact + "\n") def copy_artifacts(self, args): - '''Copy every artifact that makes up a system to an rsync path''' + '''Copy every artifact that makes up a system to an rsync path. + + Command line arguments: + + * `SYSTEM-ARTIFACT` is the filename for a build artifact for + a system (ending in `-rootfs`). + * `DESTINATION` is a URL for where the artifacts are to be + copied to, in a form suitable for the rsync program. + + This command is useful for copying artifacts from a local + system to a Morph artifact cache server, so they can be + shared by other people. It can also be used to archive + artifacts used for a release. Note, however, that it does + not include artifacts that are build-dependencies of the + strata included in the system, but not actually in cluded + in the system. + + Example: + + morph copy-artifacts /src/cache/artifacts/*.system.* \ + cache.example.com:/srv/cache/ + + ''' if len(args) != 2: raise cliapp.AppException( diff --git a/morphlib/plugins/deploy_plugin.py b/morphlib/plugins/deploy_plugin.py index a0ead149..f9560b91 100644 --- a/morphlib/plugins/deploy_plugin.py +++ b/morphlib/plugins/deploy_plugin.py @@ -49,16 +49,161 @@ class DeployPlugin(cliapp.Plugin): def deploy(self, args): '''Deploy a built system image. - - Command requires a minimum of three arguments: - morph deploy TYPE SYSTEM LOCATION + Command line arguments: + + * `TYPE` is the type of deployment: to a raw disk image, + VirtualBox, or something else. See below. + + * `SYSTEM` is the name of the system morphology to deploy. + + * `LOCATION` is where the deployed system should end up at. The + syntax depends on the deployment type. See below. + + * `KEY=VALUE` is a configuration parameter to pass onto the + configuration extension. See below. + + Morph can deploy a system image. The deployment mechanism is + quite flexible, and can be extended by the user. "Deployment" + here is quite a general concept: it covers anything where a system + image is taken, configured, and then put somewhere where it can + be run. + + `TYPE` specifies the exact way in which the deployment happens. + Morph provides four deployment types: + + * `rawdisk` where Morph builds a raw disk image at `LOCATION`, + and sets up the image with a bootloader and configuration + so that it can be booted. Disk size is set with `DISK_SIZE` + (see below). + + * `virtualbox-ssh` where Morph creates a VirtualBox disk image, + and creates a new virtual machine on a remote host, accessed + over ssh. Disk and RAM size are set with `DISK_SIZE` and + `RAM_SIZE` (see below). + + * `kvm`, which is similar to `virtualbox-ssh`, but uses libvirt + and KVM instead of VirtualBox. Disk and RAM size are set with + `DISK_SIZE` and `RAM_SIZE` (see below). + + * `nfsboot` where Morph creates a system to be booted over + a network + + The following `KEY=VALUE` parameters are supported for all + deployment types: + + * `DISK_SIZE=X` to set the size of the disk image. `X` + should use a suffix of `K`, `M`, or `G` (in upper or lower + case) to indicate kilo-, mega-, or gigabytes. For example, + `DISK_SIZE=100G` would create a 100 gigabyte disk image. **This + parameter is mandatory**. + + * `RAM_SIZE=X` to set the size of virtual RAM for the virtual + machine. `X` is interpreted in the same was as `DISK_SIZE`, + and defaults to `1G`. + + The `kvm` and `virtualbox-ssh` deployment types support an + additional parameter: + + * `AUTOSTART=<VALUE>` - allowed values are `yes` and `no` + (default) + + The syntax of the `LOCATION` depends on the deployment types. The + deployment types provided by Morph use the following syntaxes: + + * `rawdisk`: pathname to the disk image to be created; for + example, `/home/alice/testsystem.img` + + * `virtualbox-ssh` and `kvm`: a custom URL scheme that + provides the target host machine (the one that runs + VirtualBox or `kvm`), the name of the new virtual machine, + and the location on the target host of the virtual disk + file. The target host is accessed over ssh. For example, + `vbox+ssh://alice@192.168.122.1/testsys/home/alice/testsys.vdi` + or `kvm+ssh://alice@192.168.122.1/testsys/home/alice/testys.img` + where + + * `alice@192.168.122.1` is the target as given to ssh, + **from within the development host** (which may be + different from the target host's normal address); + + * `testsys` is the new VM's name; + + * `/home/alice/testsys.vdi` and `/home/alice/testys.img` are + the pathnames of the disk image files on the target host. + + For the `nfsboot` write extension, + + * LOCATION is the address of the nfsboot server. (Note this + is just the _address_ of the trove, _not_ `user@...`, since + `root@` will automatically be prepended to the server address.) + + * the following KEY=VALUE PAIRS are mandatory + + * NFSBOOT_CONFIGURE=yes (or any non-empty value). This + enables the `nfsboot` configuration extension (see + below) which MUST be used when using the `nfsboot` + write extension. + + * HOSTNAME=<STRING> a unique identifier for that system's + `nfs` root when it's deployed on the nfsboot server - the + extension creates a directory with that name for the `nfs` + root, and stores kernels by that name for the tftp server. - where + * the following KEY=VALUE PAIRS are optional - * TYPE is type of deployment - * SYSTEM is name of the system morphology to deploy - * LOCATION is the destination of the deployed system + * VERSION_LABEL=<STRING> - set the name of the system + version being deployed, when upgrading. Defaults to + "factory". + + An example command line using `morph deploy with the nfsboot` + type is + + morph deploy nfsboot devel-system-x86_64-generic \ + customer-trove \ + NFSBOOT_CONFIGURE=yes \ + HOSTNAME=test-deployment-1 \ + VERSION_LABEL=inital-test + + Each deployment type is implemented by a **write extension**. The + ones provided by Morph are listed above, but users may also + create their own by adding them in the same git repository + and branch as the system morphology. A write extension is a + script that does whatever is needed for the deployment. A write + extension is passed two command line parameters: the name of an + unpacked directory tree that contains the system files (after + configuration, see below), and the `LOCATION` argument. Any + additional `KEY=VALUE` arguments given to `morph deploy` are + set as environment variables when the write extension runs. + + Regardless of the type of deployment, the image may be + configured for a specific deployment by using **configuration + extensions**. The extensions are listed in the system morphology + file: + + ... + configuration-extensions: + - set-hostname + + The above specifies that the extension `set-hostname` is to + be run. Morph will run all the configuration extensions listed + in the system morphology, and no others. (This way, configuration + is more easily tracked in git.) + + Configuration extensions are scripts that get the unpacked + directory tree of the system as their parameter, and do whatever + is needed to configure the tree. + + Morph provides the following configuration extension built in: + + * `set-hostname` sets the hostname of the system to the value + of the `HOSTNAME` variable. + * `nfsboot` configures the system for nfsbooting. This MUST + be used when deploying with the `nfsboot` write extension. + + Any `KEY=VALUE` parameters given to `morph deploy` are set as + environment variables when either the configuration or the write + extension runs. ''' diff --git a/morphlib/plugins/expand_repo_plugin.py b/morphlib/plugins/expand_repo_plugin.py index 16087c6b..4c8ab126 100644 --- a/morphlib/plugins/expand_repo_plugin.py +++ b/morphlib/plugins/expand_repo_plugin.py @@ -22,15 +22,33 @@ import morphlib class ExpandRepoPlugin(cliapp.Plugin): '''Expand an aliased repo URL to be unaliases.''' - + def enable(self): self.app.add_subcommand( 'expand-repo', self.expand_repo, arg_synopsis='[REPOURL...]') - + def disable(self): pass - + def expand_repo(self, args): + '''Expand repo aliases in URLs. + + Command line arguments: + + * `REPOURL` is a URL that may or may not be using repository + aliases. + + See the `--repo-alias` option for more about repository aliases. + + Example: + + $ morph expand-repo baserock:baserock/morphs + Original: baserock:baserock/morphs + pull: git://trove.baserock.org/baserock/baserock/morphs + push: ssh://git@git.baserock.org/baserock/baserock/morphs + + ''' + aliases = self.app.settings['repo-alias'] resolver = morphlib.repoaliasresolver.RepoAliasResolver(aliases) for repourl in args: diff --git a/morphlib/plugins/graphing_plugin.py b/morphlib/plugins/graphing_plugin.py index 8c4ea2ef..75514eec 100644 --- a/morphlib/plugins/graphing_plugin.py +++ b/morphlib/plugins/graphing_plugin.py @@ -31,7 +31,35 @@ class GraphingPlugin(cliapp.Plugin): pass def graph_build_depends(self, args): - '''Create a visualisation of build dependencies in a stratum''' + '''Create a visualisation of build dependencies in a system. + + Command line arguments: + + * `REPO` is a repository URL. + * `REF` is a git reference (usually branch name). + * `MORPHOLOGY` is a system morphology. + + This produces a GraphViz DOT file representing all the build + dependencies within a system, based on information in the + morphologies. The GraphViz `dot` program can then be used to + create a graphical representation of the dependencies. This + can be helpful for inspecting whether there are any problems in + the dependencies. + + Example: + + morph graph-build-depends baserock:baserock/morphs master \ + devel-system-x86_64-generic > foo.dot + dot -Tpng foo.dot > foo.png + + The above would create a picture with the build dependencies of + everything in the development system for 64-bit Intel systems. + + GraphViz is not, currently, part of Baserock, so you need to run + `dot` on another system. + + ''' + for repo_name, ref, filename in self.app.itertriplets(args): self.app.status(msg='Creating build order for ' '%(repo_name)s %(ref)s %(filename)s', diff --git a/morphlib/plugins/show_dependencies_plugin.py b/morphlib/plugins/show_dependencies_plugin.py index e4e40311..856a9361 100644 --- a/morphlib/plugins/show_dependencies_plugin.py +++ b/morphlib/plugins/show_dependencies_plugin.py @@ -31,7 +31,18 @@ class ShowDependenciesPlugin(cliapp.Plugin): pass def show_dependencies(self, args): - '''Dumps the dependency tree of all input morphologies''' + '''Dumps the dependency tree of all input morphologies. + + Command line arguments: + + * `REPO` is a git repository URL. + * `REF` is a branch or other commit reference in that repository. + * `FILENAME` is a morphology filename at that ref. + + This command analyses a system morphology and produces a listing + of build dependencies of the constituent components. + + ''' if not os.path.exists(self.app.settings['cachedir']): os.mkdir(self.app.settings['cachedir']) diff --git a/morphlib/plugins/trovectl_plugin.py b/morphlib/plugins/trovectl_plugin.py index fe96cc49..7db2cbb5 100644 --- a/morphlib/plugins/trovectl_plugin.py +++ b/morphlib/plugins/trovectl_plugin.py @@ -20,12 +20,33 @@ import morphlib class TrovectlPlugin(cliapp.Plugin): def enable(self): - self.app.add_subcommand('trovectl', self.trovectl) + self.app.add_subcommand( + 'trovectl', self.trovectl, arg_synopsis='GITANO-COMMAND [ARG...]') def disable(self): pass def trovectl(self, args, **kwargs): + '''Invoke Gitano commands on the Trove host. + + Command line arguments: + + * `GITANO-COMMAND` is the Gitano command to invoke on the Trove. + * `ARG` is a Gitano command argument. + + This invokes Gitano commands on the Trove host configured + in the Morph configuration (see `--trove-host`). + + Trove is the Codethink code hosting appliance. Gitano is the + git server management component of that. + + Example: + + morph trovectl whoami + morph trovectl help + + ''' + trove = 'git@' + self.app.settings['trove-host'] self.app.runcmd(['ssh', trove] + args, stdout=None, stderr=None) diff --git a/morphlib/plugins/update_gits_plugin.py b/morphlib/plugins/update_gits_plugin.py index 083439f5..e3d7a81b 100644 --- a/morphlib/plugins/update_gits_plugin.py +++ b/morphlib/plugins/update_gits_plugin.py @@ -31,7 +31,22 @@ class UpdateGitsPlugin(cliapp.Plugin): pass def update_gits(self, args): - '''Manually update cached git repositories for the given morphology''' + '''Manually update cached git repositories for the given morphology + + Command line arguments: + + * `REPO` is a git repository URL. + * `REF` is a git commit ref (sha1, branch, tag). + * `MORPHOLOGY` is a morphology filename. + + This updates the local cached copy of a git repository, and any + git repositories of components in the morphology (for system + and stratum morphologies). + + You do not normally need to do this. Morph updates the cached + repositories automatically anyway. + + ''' app = self.app if not os.path.exists(app.settings['cachedir']): |