protected void configureOwnerAndMode(OpsTarget target, FilesystemInfo fsInfo)
      throws OpsException {
    File file = getFilePath();

    if (owner != null || group != null) {
      boolean dirty = false;

      if (fsInfo == null || (owner != null && !fsInfo.matchesOwner(owner))) {
        dirty = true;
      }

      if (fsInfo == null || (group != null && !fsInfo.matchesOwner(group))) {
        dirty = true;
      }

      if (dirty) {
        boolean recursive = false;
        boolean dereferenceSymlinks = false;
        target.chown(file, owner, group, recursive, dereferenceSymlinks);
      }
    }

    if (fileMode != null) {
      if (fsInfo != null && fsInfo.isSymlink()) {
        throw new IllegalArgumentException("File mode is meaningless on symlink");
      }

      if (fsInfo == null || !fsInfo.matchesMode(fileMode)) {
        target.chmod(file, fileMode);
      }
    }
  }
  @Handler
  public void handler(OpsTarget target) throws OpsException {
    File canaryFile = new File(repoDir, "config");

    if (OpsContext.isConfigure()) {
      if (target.getFilesystemInfoFile(canaryFile) == null) {
        target.executeCommand(Command.build("git --bare init {0}", repoDir));

        File hooks = new File(repoDir, "hooks");
        File postUpdateHook = new File(hooks, "post-update");
        target.mv(new File(hooks, "post-update.sample"), postUpdateHook);
        target.chmod(postUpdateHook, "755");

        target.executeCommand(Command.build("cd {0}; git update-server-info", repoDir));
        target.executeCommand(Command.build("cd {0}; git config http.receivepack true", repoDir));

        target.chown(repoDir, "www-data", "www-data", true, false);
      }
    }
  }