]> source.dussan.org Git - jgit.git/commitdiff
RefTreeDatabase: Allow ORIG_HEAD, etc. on non-bare repositories 01/64501/1
authorShawn Pearce <spearce@spearce.org>
Fri, 15 Jan 2016 20:46:33 +0000 (12:46 -0800)
committerShawn Pearce <spearce@spearce.org>
Fri, 15 Jan 2016 20:46:33 +0000 (12:46 -0800)
Store these in the bootstrap layer where they are using $GIT_DIR
as the storage directory for any reference that does not contain '/'.

Change-Id: I5595bf514e4475b7c7e799c2c79446597a3abb4a

org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java [new file with mode: 0644]
org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabaseTest.java
org.eclipse.jgit/src/org/eclipse/jgit/internal/storage/reftree/RefTreeDatabase.java

diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/internal/storage/reftree/LocalDiskRefTreeDatabaseTest.java
new file mode 100644 (file)
index 0000000..47f70d7
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2016 Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.eclipse.jgit.internal.storage.reftree;
+
+import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.lib.Constants.MASTER;
+import static org.eclipse.jgit.lib.Constants.ORIG_HEAD;
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.eclipse.jgit.lib.RefDatabase.ALL;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+import org.eclipse.jgit.internal.storage.file.FileRepository;
+import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
+import org.junit.Before;
+import org.junit.Test;
+
+public class LocalDiskRefTreeDatabaseTest extends LocalDiskRepositoryTestCase {
+       private FileRepository repo;
+       private RefTreeDatabase refdb;
+       private RefDatabase bootstrap;
+
+       private TestRepository<FileRepository> testRepo;
+       private RevCommit A;
+       private RevCommit B;
+
+       @Before
+       public void setUp() throws Exception {
+               FileRepository init = createWorkRepository();
+               FileBasedConfig cfg = init.getConfig();
+               cfg.setInt("core", null, "repositoryformatversion", 1);
+               cfg.setString("extensions", null, "refsStorage", "reftree");
+               cfg.save();
+
+               repo = (FileRepository) new FileRepositoryBuilder()
+                               .setGitDir(init.getDirectory())
+                               .build();
+               refdb = (RefTreeDatabase) repo.getRefDatabase();
+               bootstrap = refdb.getBootstrap();
+               addRepoToClose(repo);
+
+               RefUpdate head = refdb.newUpdate(HEAD, true);
+               head.link(R_HEADS + MASTER);
+
+               testRepo = new TestRepository<>(init);
+               A = testRepo.commit().create();
+               B = testRepo.commit(testRepo.getRevWalk().parseCommit(A));
+       }
+
+       @Test
+       public void testHeadOrigHead() throws IOException {
+               RefUpdate master = refdb.newUpdate(HEAD, false);
+               master.setExpectedOldObjectId(ObjectId.zeroId());
+               master.setNewObjectId(A);
+               assertEquals(RefUpdate.Result.NEW, master.update());
+               assertEquals(A, refdb.exactRef(HEAD).getObjectId());
+
+               RefUpdate orig = refdb.newUpdate(ORIG_HEAD, true);
+               orig.setNewObjectId(B);
+               assertEquals(RefUpdate.Result.NEW, orig.update());
+
+               File origFile = new File(repo.getDirectory(), ORIG_HEAD);
+               assertEquals(B.name() + '\n', read(origFile));
+               assertEquals(B, bootstrap.exactRef(ORIG_HEAD).getObjectId());
+               assertEquals(B, refdb.exactRef(ORIG_HEAD).getObjectId());
+               assertFalse(refdb.getRefs(ALL).containsKey(ORIG_HEAD));
+
+               List<Ref> addl = refdb.getAdditionalRefs();
+               assertEquals(2, addl.size());
+               assertEquals(ORIG_HEAD, addl.get(1).getName());
+               assertEquals(B, addl.get(1).getObjectId());
+       }
+}
index 1bacfe46f0cb75b75778292a5a499407d2ff5a22..e4d0f1d29194eaa87c03c927108bdf45621bcb3e 100644 (file)
@@ -44,6 +44,7 @@
 package org.eclipse.jgit.internal.storage.reftree;
 
 import static org.eclipse.jgit.lib.Constants.HEAD;
+import static org.eclipse.jgit.lib.Constants.ORIG_HEAD;
 import static org.eclipse.jgit.lib.Constants.R_HEADS;
 import static org.eclipse.jgit.lib.Constants.R_TAGS;
 import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
@@ -467,6 +468,27 @@ public class RefTreeDatabaseTest {
                assertEquals(txnId, getTxnCommitted());
        }
 
+       @Test
+       public void testUpdate_RefusesOrigHeadOnBare() throws IOException {
+               assertTrue(refdb.getRepository().isBare());
+               ObjectId txnId = getTxnCommitted();
+
+               RefUpdate orig = refdb.newUpdate(ORIG_HEAD, true);
+               orig.setNewObjectId(B);
+               assertEquals(RefUpdate.Result.LOCK_FAILURE, orig.update());
+               assertEquals(txnId, getTxnCommitted());
+
+               ReceiveCommand cmd = command(null, B, ORIG_HEAD);
+               BatchRefUpdate batch = refdb.newBatchUpdate();
+               batch.addCommand(cmd);
+               batch.execute(new RevWalk(repo), NullProgressMonitor.INSTANCE);
+               assertEquals(REJECTED_OTHER_REASON, cmd.getResult());
+               assertEquals(
+                               MessageFormat.format(JGitText.get().invalidRefName, ORIG_HEAD),
+                               cmd.getMessage());
+               assertEquals(txnId, getTxnCommitted());
+       }
+
        @Test
        public void testBatchRefUpdate_NonFastForwardAborts() throws IOException {
                update("refs/heads/master", A);
index f6fdef1fa5887e25be03dad03c13123446b70035..df93ce88af255d912fc833b6a486d0e1a242ede2 100644 (file)
@@ -43,6 +43,7 @@
 
 package org.eclipse.jgit.internal.storage.reftree;
 
+import static org.eclipse.jgit.lib.Constants.HEAD;
 import static org.eclipse.jgit.lib.Ref.Storage.LOOSE;
 import static org.eclipse.jgit.lib.Ref.Storage.PACKED;
 
@@ -189,12 +190,19 @@ public class RefTreeDatabase extends RefDatabase {
 
        @Override
        public Ref getRef(String name) throws IOException {
-               return findRef(getRefs(ALL), name);
+               String[] needle = new String[SEARCH_PATH.length];
+               for (int i = 0; i < SEARCH_PATH.length; i++) {
+                       needle[i] = SEARCH_PATH[i] + name;
+               }
+               return firstExactRef(needle);
        }
 
        @Override
        public Ref exactRef(String name) throws IOException {
-               if (conflictsWithBootstrap(name)) {
+               if (!repo.isBare() && name.indexOf('/') < 0 && !HEAD.equals(name)) {
+                       // Pass through names like MERGE_HEAD, ORIG_HEAD, FETCH_HEAD.
+                       return bootstrap.exactRef(name);
+               } else if (conflictsWithBootstrap(name)) {
                        return null;
                }
 
@@ -311,6 +319,9 @@ public class RefTreeDatabase extends RefDatabase {
 
        @Override
        public RefUpdate newUpdate(String name, boolean detach) throws IOException {
+               if (!repo.isBare() && name.indexOf('/') < 0 && !HEAD.equals(name)) {
+                       return bootstrap.newUpdate(name, detach);
+               }
                if (conflictsWithBootstrap(name)) {
                        return new AlwaysFailUpdate(this, name);
                }
@@ -345,7 +356,13 @@ public class RefTreeDatabase extends RefDatabase {
                        return true;
                } else if (txnCommitted.equals(name)) {
                        return true;
-               } else if (name.length() > txnCommitted.length()
+               }
+
+               if (name.indexOf('/') < 0 && !HEAD.equals(name)) {
+                       return true;
+               }
+
+               if (name.length() > txnCommitted.length()
                                && name.charAt(txnCommitted.length()) == '/'
                                && name.startsWith(txnCommitted)) {
                        return true;