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);
      }
    }
  }
  @Override
  public void copyTo0(OpsTarget target, File remoteFilePath) throws OpsException {
    InetAddress host;
    try {
      host = InetAddress.getByName(uri.getHost());
    } catch (UnknownHostException e) {
      throw new OpsException("Unable to resolve host: " + uri, e);
    }

    if (InetAddressUtils.isPublic(host)) {
      CurlRequest curlRequest = new CurlRequest(uri);
      curlRequest.bareRequest = true;
      CommandEnvironment commandEnvironment =
          httpProxies.getHttpProxyEnvironment(target, Usage.General, uri);

      Command curlCommand = curlRequest.toCommand();
      curlCommand.addLiteral(">");
      curlCommand.addFile(remoteFilePath);
      curlCommand.setEnvironment(commandEnvironment);
      curlCommand.setTimeout(TimeSpan.FIVE_MINUTES);

      target.executeCommand(curlCommand);
    } else {
      log.warn("Address was not public: " + host + ", doing copy via ops system");

      File tempFile;
      try {
        tempFile = File.createTempFile("jenkins", "dat");
      } catch (IOException e) {
        throw new OpsException("Error creating temp file", e);
      }
      try {
        InputStream is = uri.toURL().openStream();
        try {
          IoUtils.copyStream(is, tempFile);
        } finally {
          Closeables.closeQuietly(is);
        }

        FileUpload.upload(target, remoteFilePath, tempFile);
      } catch (IOException e) {
        throw new OpsException("Error copying jenkins artifact", e);
      } finally {
        tempFile.delete();
      }
    }
  }
  @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);
      }
    }
  }