public void execute() throws SVNException {
    String versionName = getRequestHeader(SVN_VERSION_NAME_HEADER);
    long version = DAVResource.INVALID_REVISION;
    try {
      version = Long.parseLong(versionName);
    } catch (NumberFormatException e) {
    }

    DAVRepositoryManager manager = getRepositoryManager();

    // use latest version, if no version was specified
    SVNRepository resourceRepository =
        SVNGitRepositoryFactory.create(SVNURL.parseURIEncoded(manager.getResourceRepositoryRoot()));
    if (version == -1) {
      version = resourceRepository.getLatestRevision();
    }
    resourceRepository.testConnection(); // to open the repository

    // get the source path to move or copy
    DAVResourceURI sourceURI =
        new DAVResourceURI(
            manager.getResourceContext(), manager.getResourcePathInfo(), null, false, version);
    String sourcePath = sourceURI.getPath();
    sourcePath = DAVPathUtil.dropLeadingSlash(sourcePath);

    String destination = getRequestHeader(HTTPHeader.DESTINATION_HEADER);
    if (destination == null) {
      String netScapeHost = getRequestHeader(HTTPHeader.HOST_HEADER);
      String netScapeNewURI = getRequestHeader(HTTPHeader.NEW_URI_HEADER);
      if (netScapeHost != null && netScapeNewURI != null) {
        String path = SVNPathUtil.append(netScapeHost, netScapeNewURI);
        if (path.startsWith("/")) {
          path = path.substring(1);
        }
        destination = "http://" + path;
      }
    }

    if (destination == null) {
      SVNDebugLog.getDefaultLog()
          .logFine(SVNLogType.NETWORK, "The request is missing a Destination header.");
      sendError(HttpServletResponse.SC_BAD_REQUEST, null);
      return;
    }

    // get the destination path to move or copy
    URI uri = DAVServletUtil.lookUpURI(destination, getRequest(), true);
    String resourceContext = manager.getResourceContext();
    String path = uri.getPath().substring(resourceContext.length());
    DAVResourceURI destinationURI =
        new DAVResourceURI(manager.getResourceContext(), path, null, false, version);
    String destinationPath = destinationURI.getPath();
    destinationPath = DAVPathUtil.dropLeadingSlash(destinationPath);

    TreeBuilder treeBuilder =
        SVNGitPropPatchHandler.treeBuilders.get(destinationURI.getActivityID());
    if (treeBuilder == null) {
      sendError(HttpServletResponse.SC_BAD_REQUEST, null);
      return;
    }

    if (myIsMove) {
      treeBuilder.move(sourcePath, destinationPath);
    } else {
      treeBuilder.copy(sourcePath, destinationPath);
    }

    handleDAVCreated(destination.toString(), "Destination", false); // FIXME: always false?
  }
  public void appendLock(DAVResource resource, DAVLock lock) throws DAVException {
    // TODO: add here authz check later
    FSFS fsfs = resource.getFSFS();
    String path = resource.getResourceURI().getPath();
    if (!resource.exists()) {
      SVNProperties revisionProps = new SVNProperties();
      revisionProps.put(SVNRevisionProperty.AUTHOR, resource.getUserName());
      DAVConfig config = resource.getRepositoryManager().getDAVConfig();
      if (resource.isSVNClient()) {
        throw new DAVException(
            "Subversion clients may not lock nonexistent paths.",
            HttpServletResponse.SC_METHOD_NOT_ALLOWED,
            DAVErrorCode.LOCK_SAVE_LOCK);
      } else if (!config.isAutoVersioning()) {
        throw new DAVException(
            "Attempted to lock non-existent path; turn on autoversioning first.",
            HttpServletResponse.SC_METHOD_NOT_ALLOWED,
            DAVErrorCode.LOCK_SAVE_LOCK);
      }

      long youngestRev = SVNRepository.INVALID_REVISION;
      try {
        youngestRev = resource.getLatestRevision();
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not determine youngest revision",
            null);
      }

      FSTransactionInfo txnInfo = null;
      try {
        txnInfo = FSTransactionRoot.beginTransactionForCommit(youngestRev, revisionProps, fsfs);
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not begin a transaction",
            null);
      }

      FSTransactionRoot root = null;
      try {
        root = fsfs.createTransactionRoot(txnInfo);
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not begin a transaction",
            null);
      }

      FSCommitter committer =
          new FSCommitter(fsfs, root, txnInfo, resource.getLockTokens(), resource.getUserName());
      try {
        committer.makeFile(path);
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not create empty file.",
            null);
      }

      try {
        DAVServletUtil.attachAutoRevisionProperties(txnInfo, path, fsfs);
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
            "Could not create empty file.",
            null);
      }

      StringBuffer conflictPath = new StringBuffer();
      try {
        committer.commitTxn(true, true, null, conflictPath);
      } catch (SVNException svne) {
        throw DAVException.convertError(
            svne.getErrorMessage(),
            HttpServletResponse.SC_CONFLICT,
            "Conflict when committing ''{0}''.",
            new Object[] {conflictPath.toString()});
      }
    }

    FSLock svnLock =
        convertDAVLockToSVNLock(
            lock, path, resource.isSVNClient(), ServletDAVHandler.getSAXParserFactory());
    try {
      fsfs.lockPath(
          path,
          svnLock.getID(),
          svnLock.getOwner(),
          svnLock.getComment(),
          svnLock.getExpirationDate(),
          myWorkingRevision,
          myIsStealLock,
          svnLock.isDAVComment());
    } catch (SVNException svne) {
      if (svne.getErrorMessage().getErrorCode() == SVNErrorCode.FS_NO_USER) {
        throw new DAVException(
            "Anonymous lock creation is not allowed.",
            HttpServletResponse.SC_UNAUTHORIZED,
            DAVErrorCode.LOCK_SAVE_LOCK);
      }
      throw DAVException.convertError(
          svne.getErrorMessage(),
          HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
          "Failed to create new lock.",
          null);
    }

    myOwner.setResponseHeader(
        HTTPHeader.CREATION_DATE_HEADER, SVNDate.formatDate(svnLock.getCreationDate()));
    myOwner.setResponseHeader(HTTPHeader.LOCK_OWNER_HEADER, svnLock.getOwner());
    // TODO: add logging here later
  }