diff --git a/scm-test/src/main/java/sonia/scm/repository/client/GitRepositoryClient.java b/scm-test/src/main/java/sonia/scm/repository/client/GitRepositoryClient.java index 66e0b2d851..42ba7459ae 100644 --- a/scm-test/src/main/java/sonia/scm/repository/client/GitRepositoryClient.java +++ b/scm-test/src/main/java/sonia/scm/repository/client/GitRepositoryClient.java @@ -40,11 +40,23 @@ import org.eclipse.jgit.api.CommitCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.RmCommand; +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheCheckout; +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TransportException; import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.RefComparator; +import org.eclipse.jgit.lib.RefUpdate; import org.eclipse.jgit.lib.TextProgressMonitor; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.FileRepository; import org.eclipse.jgit.transport.CredentialsProvider; +import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; import org.eclipse.jgit.transport.RemoteRefUpdate; @@ -61,6 +73,7 @@ import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; /** @@ -131,6 +144,28 @@ public class GitRepositoryClient implements RepositoryClient callCommand(cmd); } + /** + * Method description + * + * + * @throws RepositoryClientException + */ + @Override + public void checkout() throws RepositoryClientException + { + try + { + final FetchResult r = runFetch(); + final Ref branch = guessHEAD(r); + + doCheckout(branch); + } + catch (Exception ex) + { + throw new RepositoryClientException(ex); + } + } + /** * Method description * @@ -242,19 +277,6 @@ public class GitRepositoryClient implements RepositoryClient } } - /** - * Method description - * - * - * @throws RepositoryClientException - */ - @Override - public void update() throws RepositoryClientException - { - - // todo pull - } - /** * Method description * @@ -275,6 +297,148 @@ public class GitRepositoryClient implements RepositoryClient } } + /** + * Method description + * + * + * @param branch + * + * @throws IOException + */ + private void doCheckout(final Ref branch) throws IOException + { + if (!Constants.HEAD.equals(branch.getName())) + { + RefUpdate u = repository.updateRef(Constants.HEAD); + + u.disableRefLog(); + u.link(branch.getName()); + } + + RevCommit commit = parseCommit(branch); + RefUpdate u = repository.updateRef(Constants.HEAD); + + u.setNewObjectId(commit); + u.forceUpdate(); + + DirCache dc = repository.lockDirCache(); + DirCacheCheckout co = new DirCacheCheckout(repository, dc, + commit.getTree()); + + co.checkout(); + } + + /** + * Method description + * + * + * @param result + * + * @return + */ + private Ref guessHEAD(final FetchResult result) + { + final Ref idHEAD = result.getAdvertisedRef(Constants.HEAD); + final List availableRefs = new ArrayList(); + Ref head = null; + + for (final Ref r : result.getAdvertisedRefs()) + { + final String n = r.getName(); + + if (!n.startsWith(Constants.R_HEADS)) + { + continue; + } + + availableRefs.add(r); + + if ((idHEAD == null) || (head != null)) + { + continue; + } + + if (r.getObjectId().equals(idHEAD.getObjectId())) + { + head = r; + } + } + + Collections.sort(availableRefs, RefComparator.INSTANCE); + + if ((idHEAD != null) && (head == null)) + { + head = idHEAD; + } + + return head; + } + + /** + * Method description + * + * + * @param branch + * + * @return + * + * @throws IOException + * @throws IncorrectObjectTypeException + * @throws MissingObjectException + */ + private RevCommit parseCommit(Ref branch) + throws MissingObjectException, IncorrectObjectTypeException, + IOException + { + final RevWalk rw = new RevWalk(repository); + final RevCommit commit; + + try + { + commit = rw.parseCommit(branch.getObjectId()); + } + finally + { + rw.release(); + } + + return commit; + } + + /** + * Method description + * + * + * @return + * + * @throws NotSupportedException + * @throws TransportException + * @throws URISyntaxException + */ + private FetchResult runFetch() + throws NotSupportedException, URISyntaxException, TransportException + { + Transport tn = Transport.open(repository, Constants.HEAD); + + if (credentialsProvider != null) + { + tn.setCredentialsProvider(credentialsProvider); + } + + FetchResult r; + + try + { + r = tn.fetch(new TextProgressMonitor(), null); + } + finally + { + tn.close(); + } + + return r; + } + //~--- fields --------------------------------------------------------------- /** Field description */ diff --git a/scm-test/src/main/java/sonia/scm/repository/client/RepositoryClient.java b/scm-test/src/main/java/sonia/scm/repository/client/RepositoryClient.java index 9fa5552e68..c9b3aebace 100644 --- a/scm-test/src/main/java/sonia/scm/repository/client/RepositoryClient.java +++ b/scm-test/src/main/java/sonia/scm/repository/client/RepositoryClient.java @@ -88,5 +88,5 @@ public interface RepositoryClient * * @throws RepositoryClientException */ - public void update() throws RepositoryClientException; + public void checkout() throws RepositoryClientException; } diff --git a/scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedPermisionITCase.java b/scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedITCase.java similarity index 55% rename from scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedPermisionITCase.java rename to scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedITCase.java index 652635f2c4..cb7146e8e0 100644 --- a/scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedPermisionITCase.java +++ b/scm-webapp/src/test/java/sonia/scm/it/RepositoryExtendedITCase.java @@ -38,6 +38,9 @@ package sonia.scm.it; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; import sonia.scm.repository.Permission; import sonia.scm.repository.PermissionType; @@ -56,23 +59,45 @@ import static sonia.scm.it.IntegrationTestUtil.*; import com.sun.jersey.api.client.Client; import com.sun.jersey.api.client.ClientResponse; +import com.sun.jersey.api.client.GenericType; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.UUID; /** * * @author Sebastian Sdorra */ -public class RepositoryExtendedPermisionITCase +@RunWith(Parameterized.class) +public class RepositoryExtendedITCase { - /** Field description */ - private static Repository REPOSITORY = null; + /** + * Constructs ... + * + * + * + * @param repository + * @param username + * @param password + * + * @throws IOException + * @throws RepositoryClientException + */ + public RepositoryExtendedITCase(Repository repository, String username, + String password) + throws RepositoryClientException, IOException + { + this.repository = repository; + this.username = username; + this.password = password; + } //~--- methods -------------------------------------------------------------- @@ -86,10 +111,40 @@ public class RepositoryExtendedPermisionITCase Client client = createAdminClient(); createResource(client, "users/trillian").delete(); - createResource(client, "repositories/" + REPOSITORY.getId()).delete(); + + Collection repositories = + createResource(client, "repositories").get( + new GenericType>() {} + ); + + if (repositories != null) + { + for (Repository r : repositories) + { + createResource(client, "repositories/" + r.getId()).delete(); + } + } + client.destroy(); } + /** + * Method description + * + * + * @return + */ + @Parameters + public static Collection createParameters() + { + Collection params = new ArrayList(); + Repository repository = createRepository("git", "trillian"); + + params.add(new Object[] { repository, "trillian", "secret" }); + + return params; + } + /** * Method description * @@ -102,19 +157,6 @@ public class RepositoryExtendedPermisionITCase trillian.setPassword("secret"); createResource(client, "users").post(trillian); - - Repository repository = RepositoryTestData.createHeartOfGold("git"); - - repository.setPermissions(Arrays.asList(new Permission("trillian", - PermissionType.WRITE))); - - ClientResponse response = createResource(client, - "repositories").post(ClientResponse.class, - repository); - String url = response.getHeaders().get("Location").get(0) + EXTENSION; - - response.close(); - REPOSITORY = client.resource(url).get(Repository.class); client.destroy(); } @@ -123,26 +165,30 @@ public class RepositoryExtendedPermisionITCase * * * + * @param repository + * @param username + * @param password + * * @throws IOException * @throws RepositoryClientException */ - @Test - public void write() throws RepositoryClientException, IOException + private static void addTestFiles(Repository repository, String username, + String password) + throws RepositoryClientException, IOException { - File directory = new File(System.getProperty("java.io.tmpdir"), - UUID.randomUUID().toString()); + File directory = createTempDirectory(); try { - RepositoryClient rc = RepositoryClientFactory.createClient("git", - directory, REPOSITORY.getUrl(), "trillian", - "secret"); + RepositoryClient rc = + RepositoryClientFactory.createClient(repository.getType(), directory, + repository.getUrl(), username, password); rc.init(); for (int i = 0; i < 5; i++) { - createRandomFile(rc, directory, i); + createRandomFile(rc, directory); } rc.commit("added some test files"); @@ -160,21 +206,21 @@ public class RepositoryExtendedPermisionITCase * * @param client * @param directory - * @param i * * @throws IOException * @throws RepositoryClientException */ - private void createRandomFile(RepositoryClient client, File directory, int i) + private static void createRandomFile(RepositoryClient client, File directory) throws IOException, RepositoryClientException { - String name = "file-" + i + ".uuid"; + String uuid = UUID.randomUUID().toString(); + String name = "file-" + uuid + ".uuid"; FileOutputStream out = null; try { out = new FileOutputStream(new File(directory, name)); - out.write(UUID.randomUUID().toString().getBytes()); + out.write(uuid.getBytes()); } finally { @@ -183,4 +229,101 @@ public class RepositoryExtendedPermisionITCase client.add(name); } + + /** + * Method description + * + * + * @param type + * @param username + * + * @return + */ + private static Repository createRepository(String type, String username) + { + Client client = createAdminClient(); + Repository repository = RepositoryTestData.createHeartOfGold(type); + + repository.setPermissions(Arrays.asList(new Permission(username, + PermissionType.WRITE))); + + ClientResponse response = createResource(client, + "repositories").post(ClientResponse.class, + repository); + String url = response.getHeaders().get("Location").get(0) + EXTENSION; + + response.close(); + repository = client.resource(url).get(Repository.class); + client.destroy(); + + return repository; + } + + /** + * Method description + * + * + * @return + */ + private static File createTempDirectory() + { + File directory = new File(System.getProperty("java.io.tmpdir"), + UUID.randomUUID().toString()); + + IOUtil.mkdirs(directory); + + return directory; + } + + /** + * Method description + * + * + * @throws IOException + * @throws RepositoryClientException + */ + @Test + public void read() throws RepositoryClientException, IOException + { + File directory = createTempDirectory(); + + try + { + RepositoryClient rc = + RepositoryClientFactory.createClient(repository.getType(), directory, + repository.getUrl(), username, password); + + rc.init(); + rc.checkout(); + } + finally + { + IOUtil.delete(directory); + } + } + + /** + * Method description + * + * + * + * @throws IOException + * @throws RepositoryClientException + */ + @Test + public void write() throws RepositoryClientException, IOException + { + addTestFiles(repository, username, password); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private String password; + + /** Field description */ + private Repository repository; + + /** Field description */ + private String username; }