anchor.diff:        });
   }
   
  -Future _doCommitComplex(TaskContext ctx, String workTree, String gitDir) {
  +Future _doCommitComplex(TaskContext ctx, String workTree, String gitDir,
  +                        String commitMessage) {
  +  requireArgumentNotNullOrEmpty(commitMessage, 'commitMessage');
  +
     final args = _getGitArgs(gitDir, workTree, ['add', '--all']);
     return Process.run('git', args)
         .chain((ProcessResult pr) {
           _throwIfProcessFailed(ctx, pr);
   
           // TODO: need more info for commit message
  -        final args = _getGitArgs(gitDir, workTree, ['commit', '-m', 'new goodness', '.']);
  +        final args = _getGitArgs(gitDir, workTree,
  +            ['commit', '-m', commitMessage, '.']);
   
           return Process.run('git', args);
         })
  
positive.code:             .chain((obj) => _deleteTempDirs([outputDir, gitDir]))
              .transform((obj) => true);
    });
  }
  
  Future _deleteTempDirs(Collection<String> dirPaths) {
  
negative.code:   final tempGitDirFuture = dir.createTemp()
        .chain((Directory dir) => _doGitCheckout(ctx, '.', dir.path, targetBranch));
    final getLibsFuture = libGetter();
    final commitMessageFuture = _getCommitMessageFuture(ctx);
  
    return Futures.wait([tempDocsDirFuture, getLibsFuture, tempGitDirFuture,
                         commitMessageFuture])
        .chain((values) {
          final outputDir = values[0];
          final libs = values[1];
          final gitDir = values[2];
          final commitMessage = values[3];
          return _ensureProperBranch(ctx, gitDir, outputDir, targetBranch)
              .chain((obj) => _dartDoc(ctx, outputDir, libs))
              .chain((bool dartDocSuccess) {
                if(dartDocSuccess) {
                  return _doCommitComplex(ctx, outputDir, gitDir, commitMessage);
                } else {
                  throw 'boo! docs failed...clean up';
                }
  