From 3101f321a30300ebed7c4716c9c9d45119eca309 Mon Sep 17 00:00:00 2001 From: Grzegorz Grzybek Date: Mon, 26 Oct 2015 11:02:05 +0100 Subject: [PATCH] =?UTF-8?q?[git-patching][ENTESB-4184]=20Add=20some=20hack?= =?UTF-8?q?s=20to=20make=20fast=20filesystem=20operations=20work=20on=20Wi?= =?UTF-8?q?ndows=E2=84=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fabric8/patch/management/PatchData.java | 1 + .../fabric8/patch/management/PatchResult.java | 1 + .../io/fabric8/patch/management/Utils.java | 8 +-- .../impl/GitPatchManagementServiceImpl.java | 48 ++++++++------- .../management/impl/GitPatchRepository.java | 9 +++ .../impl/GitPatchRepositoryImpl.java | 7 +++ .../management/io/EOLFixingFileUtils.java | 13 +++- .../io/NtfsAwareCheckoutCommand.java | 59 +++++++++++++++++++ .../patch/management/io/ProfileFileUtils.java | 13 +++- 9 files changed, 130 insertions(+), 29 deletions(-) create mode 100644 patch/patch-management/src/main/java/io/fabric8/patch/management/io/NtfsAwareCheckoutCommand.java diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/PatchData.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/PatchData.java index 0cca7612f59..6c94e98e239 100644 --- a/patch/patch-management/src/main/java/io/fabric8/patch/management/PatchData.java +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/PatchData.java @@ -100,6 +100,7 @@ public PatchData(String id, String description, List bundles, List versions = new TreeMap<>(); - fork.checkout().setName(gitPatchRepository.getFuseRootContainerPatchBranchName()).call(); + gitPatchRepository.checkout(fork) + .setName(gitPatchRepository.getFuseRootContainerPatchBranchName()) + .call(); // we'll look for Fuse/AMQ baseline in /patches dir too - it doesn't have to be present versions.put(new Version(currentFuseVersion), patchesDir); @@ -2126,7 +2132,9 @@ private void trackBaselinesForRootContainer(Git fork) throws IOException, GitAPI versionDirs = new File(systemRepo, "org/jboss/amq/jboss-a-mq").listFiles(); versions.clear(); - fork.checkout().setName(gitPatchRepository.getAmqRootContainerPatchBranchName()).call(); + gitPatchRepository.checkout(fork) + .setName(gitPatchRepository.getAmqRootContainerPatchBranchName()) + .call(); // we'll look for Fuse/AMQ baseline in /patches dir too - it doesn't have to be present versions.put(new Version(currentFuseVersion), patchesDir); @@ -2241,14 +2249,14 @@ private RevCommit trackBaselineRepository(Git git, File baselineDistribution, St */ private void trackFabricContainerBaselineRepository(Git fork, String version) throws IOException, GitAPIException { if (fork.getRepository().getRef("refs/heads/" + gitPatchRepository.getMainBranchName()) == null) { - fork.checkout() + gitPatchRepository.checkout(fork) .setName(gitPatchRepository.getMainBranchName()) .setStartPoint("patch-management^{commit}") .setCreateBranch(true) .setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK) .call(); } else { - fork.checkout() + gitPatchRepository.checkout(fork) .setName(gitPatchRepository.getMainBranchName()) .call(); } @@ -2717,7 +2725,7 @@ public boolean alignTo(Map versions) throws PatchException { // we have to be at that tag Git mainRepository = gitPatchRepository.findOrCreateMainGitRepository(); fork = gitPatchRepository.cloneRepository(mainRepository, true); - fork.checkout() + gitPatchRepository.checkout(fork) .setName(gitPatchRepository.getMainBranchName()) .call(); diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepository.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepository.java index 5cc4bbab296..883099a6928 100644 --- a/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepository.java +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepository.java @@ -23,6 +23,7 @@ import java.util.Map; import io.fabric8.patch.management.ManagedPatch; +import org.eclipse.jgit.api.CheckoutCommand; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; @@ -84,6 +85,14 @@ public interface GitPatchRepository { */ void closeRepository(Git git, boolean deleteWorkingCopy); + /** + * Special git checkout that does several attempts to checkout a revision. This is mainly for + * Windows... + * @param git + * @return + */ + CheckoutCommand checkout(Git git); + /** * Checks whether a branch in repository contains named commit * @param git diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepositoryImpl.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepositoryImpl.java index 5e923142423..cfee8725a07 100644 --- a/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepositoryImpl.java +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/impl/GitPatchRepositoryImpl.java @@ -29,6 +29,8 @@ import io.fabric8.patch.management.ManagedPatch; import org.apache.commons.io.FileUtils; +import org.eclipse.jgit.api.CheckoutCommand; +import io.fabric8.patch.management.io.NtfsAwareCheckoutCommand; import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.CreateBranchCommand; import org.eclipse.jgit.api.Git; @@ -257,6 +259,11 @@ public void closeRepository(Git git, boolean deleteWorkingCopy) { } } + @Override + public CheckoutCommand checkout(Git git) { + return new NtfsAwareCheckoutCommand(git.getRepository()); + } + @Override public boolean containsCommit(Git git, String branch, String commitMessage) throws IOException, GitAPIException { ObjectId head = git.getRepository().resolve(branch); diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/io/EOLFixingFileUtils.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/EOLFixingFileUtils.java index 359f7ef905d..2861f678f3d 100644 --- a/patch/patch-management/src/main/java/io/fabric8/patch/management/io/EOLFixingFileUtils.java +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/EOLFixingFileUtils.java @@ -90,7 +90,18 @@ private static void doCopyDirectory(File srcDir, File baseDestDir, File destDir, throw new IOException("Destination '" + destDir + "' exists but is not a directory"); } } else { - if (!destDir.mkdirs() && !destDir.isDirectory()) { + for (int i=0; i<10; i++) { + if (!destDir.mkdirs()) { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } else { + break; + } + } + if (!destDir.isDirectory()) { throw new IOException("Destination '" + destDir + "' directory cannot be created"); } } diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/io/NtfsAwareCheckoutCommand.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/NtfsAwareCheckoutCommand.java new file mode 100644 index 00000000000..abcd2ca40f9 --- /dev/null +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/NtfsAwareCheckoutCommand.java @@ -0,0 +1,59 @@ +/** + * Copyright 2005-2015 Red Hat, Inc. + * + * Red Hat licenses this file to you under the Apache License, version + * 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + * implied. See the License for the specific language governing + * permissions and limitations under the License. + */ +package io.fabric8.patch.management.io; + +import org.eclipse.jgit.api.CheckoutCommand; +import org.eclipse.jgit.api.errors.GitAPIException; +import org.eclipse.jgit.api.errors.JGitInternalException; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; + +public class NtfsAwareCheckoutCommand extends CheckoutCommand { + + /** + * @param repo + */ + public NtfsAwareCheckoutCommand(Repository repo) { + super(repo); + } + + @Override + public Ref call() throws GitAPIException { + JGitInternalException lastException = null; + for (int i=0; i<5; i++) { + try { + return super.call(); + } catch (JGitInternalException e) { + if (!e.getMessage().toLowerCase().contains("Could not rename file")) { + throw e; + } else { + lastException = e; + } + try { + Thread.sleep(250); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + } + } + } + if (lastException != null) { + throw lastException; + } else { + return null; + } + } + +} diff --git a/patch/patch-management/src/main/java/io/fabric8/patch/management/io/ProfileFileUtils.java b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/ProfileFileUtils.java index 638d534a926..73abf8614ed 100644 --- a/patch/patch-management/src/main/java/io/fabric8/patch/management/io/ProfileFileUtils.java +++ b/patch/patch-management/src/main/java/io/fabric8/patch/management/io/ProfileFileUtils.java @@ -104,7 +104,18 @@ private static void doCopyDirectory(File srcDir, File destDir, List excl throw new IOException("Destination '" + destDir + "' exists but is not a directory"); } } else { - if (!destDir.mkdirs() && !destDir.isDirectory()) { + for (int i=0; i<10; i++) { + if (!destDir.mkdirs()) { + try { + Thread.sleep(250); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } else { + break; + } + } + if (!destDir.isDirectory()) { throw new IOException("Destination '" + destDir + "' directory cannot be created"); } }