/*
 * Copyright (C) 2019, Google Inc. and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.internal.storage.file;

import static org.eclipse.jgit.lib.RefUpdate.Result.FAST_FORWARD;
import static org.eclipse.jgit.lib.RefUpdate.Result.FORCED;
import static org.eclipse.jgit.lib.RefUpdate.Result.IO_FAILURE;
import static org.eclipse.jgit.lib.RefUpdate.Result.LOCK_FAILURE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.File;
import java.io.IOException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.ReflogReader;
import org.eclipse.jgit.lib.RepositoryCache;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.test.resources.SampleDataRepositoryTestCase;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.junit.Test;

public class FileReftableTest extends SampleDataRepositoryTestCase {
	String bCommit;

	@Override
	public void setUp() throws Exception {
		super.setUp();
		Ref b = db.exactRef("refs/heads/b");
		bCommit = b.getObjectId().getName();
		db.convertToReftable(false, false);
	}

	@SuppressWarnings("boxing")
	@Test
	public void testRacyReload() throws Exception {
		ObjectId id = db.resolve("master");
		int retry = 0;
		try (FileRepository repo1 = new FileRepository(db.getDirectory());
				FileRepository repo2 = new FileRepository(db.getDirectory())) {
			FileRepository repos[] = { repo1, repo2 };
			for (int i = 0; i < 10; i++) {
				for (int j = 0; j < 2; j++) {
					FileRepository repo = repos[j];
					RefUpdate u = repo.getRefDatabase().newUpdate(
							String.format("branch%d", i * 10 + j), false);

					u.setNewObjectId(id);
					RefUpdate.Result r = u.update();
					if (!r.equals(Result.NEW)) {
						retry++;
						u = repo.getRefDatabase().newUpdate(
								String.format("branch%d", i * 10 + j), false);

						u.setNewObjectId(id);
						r = u.update();
						assertEquals(r, Result.NEW);
					}
				}
			}

			// only the first one succeeds
			assertEquals(retry, 19);
		}
	}

	@Test
	public void testCompactFully() throws Exception {
		ObjectId c1 = db.resolve("master^^");
		ObjectId c2 = db.resolve("master^");
		for (int i = 0; i < 5; i++) {
			RefUpdate u = db.updateRef("refs/heads/master");
			u.setForceUpdate(true);
			u.setNewObjectId((i%2) == 0 ? c1 : c2);
			assertEquals(u.update(), FORCED);
		}

		File tableDir = new File(db.getDirectory(), Constants.REFTABLE);
		assertTrue(tableDir.listFiles().length > 2);
		((FileReftableDatabase)db.getRefDatabase()).compactFully();
		assertEquals(tableDir.listFiles().length,2);
	}

	@Test
	public void testOpenConvert() throws Exception {
		try (FileRepository repo = new FileRepository(db.getDirectory())) {
			assertTrue(repo.getRefDatabase() instanceof FileReftableDatabase);
		}
	}

	@Test
	public void testConvert() throws Exception {
		Ref h = db.exactRef("HEAD");
		assertTrue(h.isSymbolic());
		assertEquals("refs/heads/master", h.getTarget().getName());

		Ref b = db.exactRef("refs/heads/b");
		assertFalse(b.isSymbolic());
		assertTrue(b.isPeeled());
		assertEquals(bCommit, b.getObjectId().name());

		assertTrue(db.getRefDatabase().hasFastTipsWithSha1());
	}

	@Test
	public void testConvertToRefdir() throws Exception {
		db.convertToPackedRefs(false, false);
		assertTrue(db.getRefDatabase() instanceof RefDirectory);
		Ref h = db.exactRef("HEAD");
		assertTrue(h.isSymbolic());
		assertEquals("refs/heads/master", h.getTarget().getName());

		Ref b = db.exactRef("refs/heads/b");
		assertFalse(b.isSymbolic());
		assertTrue(b.isPeeled());
		assertEquals(bCommit, b.getObjectId().name());

		assertFalse(db.getRefDatabase().hasFastTipsWithSha1());
	}

	@Test
	public void testConvertToRefdirReflog() throws Exception {
		Ref a = db.exactRef("refs/heads/a");
		String aCommit = a.getObjectId().getName();
		RefUpdate u = db.updateRef("refs/heads/master");
		u.setForceUpdate(true);
		u.setNewObjectId(ObjectId.fromString(aCommit));
		u.setForceRefLog(true);
		u.setRefLogMessage("apple", false);
		u.update();

		RefUpdate v = db.updateRef("refs/heads/master");
		v.setForceUpdate(true);
		v.setNewObjectId(ObjectId.fromString(bCommit));
		v.setForceRefLog(true);
		v.setRefLogMessage("banana", false);
		v.update();

		db.convertToPackedRefs(true, false);
		List<ReflogEntry> logs = db.getReflogReader("refs/heads/master").getReverseEntries(2);
		assertEquals(logs.get(0).getComment(), "banana");
		assertEquals(logs.get(1).getComment(), "apple");
	}

	@Test
	public void testBatchrefUpdate() throws Exception {
		ObjectId cur = db.resolve("master");
		ObjectId prev = db.resolve("master^");

		PersonIdent person = new PersonIdent("name", "mail@example.com");
		ReceiveCommand rc1 = new ReceiveCommand(ObjectId.zeroId(), cur, "refs/heads/batch1");
		ReceiveCommand rc2 = new ReceiveCommand(ObjectId.zeroId(), prev, "refs/heads/batch2");
		String msg =  "message";
		try (RevWalk rw = new RevWalk(db)) {
			db.getRefDatabase().newBatchUpdate()
					.addCommand(rc1, rc2)
					.setAtomic(true)
					.setRefLogIdent(person)
					.setRefLogMessage(msg, false)
					.execute(rw, NullProgressMonitor.INSTANCE);
		}

		assertEquals(rc1.getResult(), ReceiveCommand.Result.OK);
		assertEquals(rc2.getResult(), ReceiveCommand.Result.OK);

		ReflogEntry e = db.getReflogReader("refs/heads/batch1").getLastEntry();
		assertEquals(msg, e.getComment());
		assertEquals(person, e.getWho());
		assertEquals(cur, e.getNewId());

		e = db.getReflogReader("refs/heads/batch2").getLastEntry();
		assertEquals(msg, e.getComment());
		assertEquals(person, e.getWho());
		assertEquals(prev, e.getNewId());

		assertEquals(cur, db.exactRef("refs/heads/batch1").getObjectId());
		assertEquals(prev, db.exactRef("refs/heads/batch2").getObjectId());
	}

	@Test
	public void testFastforwardStatus() throws Exception {
		ObjectId cur = db.resolve("master");
		ObjectId prev = db.resolve("master^");
		RefUpdate u = db.updateRef("refs/heads/master");

		u.setNewObjectId(prev);
		u.setForceUpdate(true);
		assertEquals(FORCED, u.update());

		RefUpdate u2 = db.updateRef("refs/heads/master");

		u2.setNewObjectId(cur);
		assertEquals(FAST_FORWARD, u2.update());
	}

	@Test
	public void testUpdateChecksOldValue() throws Exception {
		ObjectId cur = db.resolve("master");
		ObjectId prev = db.resolve("master^");
		RefUpdate u1 = db.updateRef("refs/heads/master");
		RefUpdate u2 = db.updateRef("refs/heads/master");

		u1.setExpectedOldObjectId(cur);
		u1.setNewObjectId(prev);
		u1.setForceUpdate(true);

		u2.setExpectedOldObjectId(cur);
		u2.setNewObjectId(prev);
		u2.setForceUpdate(true);

		assertEquals(FORCED, u1.update());
		assertEquals(LOCK_FAILURE, u2.update());
	}

	@Test
	public void testWritesymref() throws Exception {
		writeSymref(Constants.HEAD, "refs/heads/a");
		assertNotNull(db.exactRef("refs/heads/b"));
	}

	@Test
	public void testFastforwardStatus2() throws Exception {
		writeSymref(Constants.HEAD, "refs/heads/a");
		ObjectId bId = db.exactRef("refs/heads/b").getObjectId();
		RefUpdate u = db.updateRef("refs/heads/a");
		u.setNewObjectId(bId);
		u.setRefLogMessage("Setup", false);
		assertEquals(FAST_FORWARD, u.update());
	}

	@Test
	public void testDelete() throws Exception {
		RefUpdate up = db.getRefDatabase().newUpdate("refs/heads/a", false);
		up.setForceUpdate(true);
		RefUpdate.Result res = up.delete();
		assertEquals(res, FORCED);
		assertNull(db.exactRef("refs/heads/a"));
	}

	@Test
	public void testDeleteWithoutHead() throws IOException {
		// Prepare repository without HEAD
		RefUpdate refUpdate = db.updateRef(Constants.HEAD, true);
		refUpdate.setForceUpdate(true);
		refUpdate.setNewObjectId(ObjectId.zeroId());

		RefUpdate.Result updateResult = refUpdate.update();
		assertEquals(FORCED, updateResult);

		Ref r = db.exactRef("HEAD");
		assertEquals(ObjectId.zeroId(), r.getObjectId());
		RefUpdate.Result deleteHeadResult = db.updateRef(Constants.HEAD)
				.delete();

		// why does doDelete say NEW ?
		assertEquals(RefUpdate.Result.NO_CHANGE, deleteHeadResult);

		// Any result is ok as long as it's not an NPE
		db.updateRef(Constants.R_HEADS + "master").delete();
	}

	@Test
	public void testUpdateRefDetached() throws Exception {
		ObjectId pid = db.resolve("refs/heads/master");
		ObjectId ppid = db.resolve("refs/heads/master^");
		RefUpdate updateRef = db.updateRef("HEAD", true);
		updateRef.setForceUpdate(true);
		updateRef.setNewObjectId(ppid);
		RefUpdate.Result update = updateRef.update();
		assertEquals(FORCED, update);
		assertEquals(ppid, db.resolve("HEAD"));
		Ref ref = db.exactRef("HEAD");
		assertEquals("HEAD", ref.getName());
		assertTrue("is detached", !ref.isSymbolic());

		// the branch HEAD referred to is left untouched
		assertEquals(pid, db.resolve("refs/heads/master"));
		ReflogReader reflogReader = db.getReflogReader("HEAD");
		ReflogEntry e = reflogReader.getReverseEntries().get(0);
		assertEquals(ppid, e.getNewId());
		assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
		assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
		assertEquals(1250379778000L, e.getWho().getWhen().getTime());
		assertEquals(pid, e.getOldId());
	}

	@Test
	public void testWriteReflog() throws Exception {
		ObjectId pid = db.resolve("refs/heads/master^");
		RefUpdate updateRef = db.updateRef("refs/heads/master");
		updateRef.setNewObjectId(pid);
		String msg = "REFLOG!";
		updateRef.setRefLogMessage(msg, true);
		PersonIdent person = new PersonIdent("name", "mail@example.com");
		updateRef.setRefLogIdent(person);
		updateRef.setForceUpdate(true);
		RefUpdate.Result update = updateRef.update();
		assertEquals(FORCED, update); // internal
		ReflogReader r = db.getReflogReader("refs/heads/master");

		ReflogEntry e = r.getLastEntry();
		assertEquals(e.getNewId(), pid);
		assertEquals(e.getComment(), "REFLOG!: FORCED");
		assertEquals(e.getWho(), person);
	}

	@Test
	public void testLooseDelete() throws IOException {
		final String newRef = "refs/heads/abc";
		assertNull(db.exactRef(newRef));

		RefUpdate ref = db.updateRef(newRef);
		ObjectId nonZero = db.resolve(Constants.HEAD);
		assertNotEquals(nonZero, ObjectId.zeroId());
		ref.setNewObjectId(nonZero);
		assertEquals(RefUpdate.Result.NEW, ref.update());

		ref = db.updateRef(newRef);
		ref.setNewObjectId(db.resolve(Constants.HEAD));

		assertEquals(ref.delete(), RefUpdate.Result.NO_CHANGE);

		// Differs from RefupdateTest. Deleting a loose ref leaves reflog trail.
		ReflogReader reader = db.getReflogReader("refs/heads/abc");
		assertEquals(ObjectId.zeroId(), reader.getReverseEntry(1).getOldId());
		assertEquals(nonZero, reader.getReverseEntry(1).getNewId());
		assertEquals(nonZero, reader.getReverseEntry(0).getOldId());
		assertEquals(ObjectId.zeroId(), reader.getReverseEntry(0).getNewId());
	}

	private static class SubclassedId extends ObjectId {
		SubclassedId(AnyObjectId src) {
			super(src);
		}
	}

	@Test
	public void testNoCacheObjectIdSubclass() throws IOException {
		final String newRef = "refs/heads/abc";
		final RefUpdate ru = updateRef(newRef);
		final SubclassedId newid = new SubclassedId(ru.getNewObjectId());
		ru.setNewObjectId(newid);
		RefUpdate.Result update = ru.update();
		assertEquals(RefUpdate.Result.NEW, update);
		Ref r = db.exactRef(newRef);
		assertEquals(newRef, r.getName());
		assertNotNull(r.getObjectId());
		assertNotSame(newid, r.getObjectId());
		assertSame(ObjectId.class, r.getObjectId().getClass());
		assertEquals(newid, r.getObjectId());
		List<ReflogEntry> reverseEntries1 = db.getReflogReader("refs/heads/abc")
				.getReverseEntries();
		ReflogEntry entry1 = reverseEntries1.get(0);
		assertEquals(1, reverseEntries1.size());
		assertEquals(ObjectId.zeroId(), entry1.getOldId());
		assertEquals(r.getObjectId(), entry1.getNewId());

		assertEquals(new PersonIdent(db).toString(),
				entry1.getWho().toString());
		assertEquals("", entry1.getComment());
		List<ReflogEntry> reverseEntries2 = db.getReflogReader("HEAD")
				.getReverseEntries();
		assertEquals(0, reverseEntries2.size());
	}

	@Test
	public void testDeleteSymref() throws IOException {
		RefUpdate dst = updateRef("refs/heads/abc");
		assertEquals(RefUpdate.Result.NEW, dst.update());
		ObjectId id = dst.getNewObjectId();

		RefUpdate u = db.updateRef("refs/symref");
		assertEquals(RefUpdate.Result.NEW, u.link(dst.getName()));

		Ref ref = db.exactRef(u.getName());
		assertNotNull(ref);
		assertTrue(ref.isSymbolic());
		assertEquals(dst.getName(), ref.getLeaf().getName());
		assertEquals(id, ref.getLeaf().getObjectId());

		u = db.updateRef(u.getName());
		u.setDetachingSymbolicRef();
		u.setForceUpdate(true);
		assertEquals(FORCED, u.delete());

		assertNull(db.exactRef(u.getName()));
		ref = db.exactRef(dst.getName());
		assertNotNull(ref);
		assertFalse(ref.isSymbolic());
		assertEquals(id, ref.getObjectId());
	}

	@Test
	public void writeUnbornHead() throws Exception {
		RefUpdate.Result r = db.updateRef("HEAD").link("refs/heads/unborn");
		assertEquals(FORCED, r);

		Ref head = db.exactRef("HEAD");
		assertTrue(head.isSymbolic());
		assertEquals(head.getTarget().getName(), "refs/heads/unborn");
	}

	/**
	 * Update the HEAD ref when the referenced branch is unborn
	 *
	 * @throws Exception
	 */
	@Test
	public void testUpdateRefDetachedUnbornHead() throws Exception {
		ObjectId ppid = db.resolve("refs/heads/master^");
		writeSymref("HEAD", "refs/heads/unborn");
		RefUpdate updateRef = db.updateRef("HEAD", true);
		updateRef.setForceUpdate(true);
		updateRef.setNewObjectId(ppid);
		RefUpdate.Result update = updateRef.update();
		assertEquals(RefUpdate.Result.NEW, update);
		assertEquals(ppid, db.resolve("HEAD"));
		Ref ref = db.exactRef("HEAD");
		assertEquals("HEAD", ref.getName());
		assertTrue("is detached", !ref.isSymbolic());

		// the branch HEAD referred to is left untouched
		assertNull(db.resolve("refs/heads/unborn"));
		ReflogReader reflogReader = db.getReflogReader("HEAD");
		ReflogEntry e = reflogReader.getReverseEntries().get(0);
		assertEquals(ObjectId.zeroId(), e.getOldId());
		assertEquals(ppid, e.getNewId());
		assertEquals("GIT_COMMITTER_EMAIL", e.getWho().getEmailAddress());
		assertEquals("GIT_COMMITTER_NAME", e.getWho().getName());
		assertEquals(1250379778000L, e.getWho().getWhen().getTime());
	}

	@Test
	public void testDeleteNotFound() throws IOException {
		RefUpdate ref = updateRef("refs/heads/doesnotexist");
		assertNull(db.exactRef(ref.getName()));
		assertEquals(RefUpdate.Result.NEW, ref.delete());
		assertNull(db.exactRef(ref.getName()));
	}

	@Test
	public void testRenameSymref() throws IOException {
		db.resolve("HEAD");
		RefRename r = db.renameRef("HEAD", "KOPF");
		assertEquals(IO_FAILURE, r.rename());
	}

	@Test
	public void testRenameCurrentBranch() throws IOException {
		ObjectId rb = db.resolve("refs/heads/b");
		writeSymref(Constants.HEAD, "refs/heads/b");
		ObjectId oldHead = db.resolve(Constants.HEAD);
		assertEquals("internal test condition, b == HEAD", oldHead, rb);
		RefRename renameRef = db.renameRef("refs/heads/b",
				"refs/heads/new/name");
		RefUpdate.Result result = renameRef.rename();
		assertEquals(RefUpdate.Result.RENAMED, result);
		assertEquals(rb, db.resolve("refs/heads/new/name"));
		assertNull(db.resolve("refs/heads/b"));
		assertEquals(rb, db.resolve(Constants.HEAD));

		List<String> names = new ArrayList<>();
		names.add("HEAD");
		names.add("refs/heads/b");
		names.add("refs/heads/new/name");

		for (String nm : names) {
			ReflogReader rd = db.getReflogReader(nm);
			assertNotNull(rd);
			ReflogEntry last = rd.getLastEntry();
			ObjectId id = last.getNewId();
			assertTrue(ObjectId.zeroId().equals(id) || rb.equals(id));

			id = last.getNewId();
			assertTrue(ObjectId.zeroId().equals(id) || rb.equals(id));

			String want = "Branch: renamed b to new/name";
			assertEquals(want, last.getComment());
		}
	}

	@Test
	public void isGitRepository() {
		assertTrue(RepositoryCache.FileKey.isGitRepository(db.getDirectory(), db.getFS()));
	}

	@Test
	public void testRenameDestExists() throws IOException {
		ObjectId rb = db.resolve("refs/heads/b");
		writeSymref(Constants.HEAD, "refs/heads/b");
		ObjectId oldHead = db.resolve(Constants.HEAD);
		assertEquals("internal test condition, b == HEAD", oldHead, rb);
		RefRename renameRef = db.renameRef("refs/heads/b", "refs/heads/a");
		RefUpdate.Result result = renameRef.rename();
		assertEquals(RefUpdate.Result.LOCK_FAILURE, result);
	}

	@Test
	public void testRenameAtomic() throws IOException {
		ObjectId prevId = db.resolve("refs/heads/master^");

		RefRename rename = db.renameRef("refs/heads/master",
				"refs/heads/newmaster");

		RefUpdate updateRef = db.updateRef("refs/heads/master");
		updateRef.setNewObjectId(prevId);
		updateRef.setForceUpdate(true);
		assertEquals(FORCED, updateRef.update());
		assertEquals(RefUpdate.Result.LOCK_FAILURE, rename.rename());
	}

	@Test
	public void compactFully() throws Exception {
		FileReftableDatabase refDb = (FileReftableDatabase) db.getRefDatabase();
		PersonIdent person = new PersonIdent("jane", "jane@invalid");

		ObjectId aId  = db.exactRef("refs/heads/a").getObjectId();
		ObjectId bId  = db.exactRef("refs/heads/b").getObjectId();

		SecureRandom random = new SecureRandom();
		List<String> strs = new ArrayList<>();
		for (int i = 0; i < 1024; i++) {
			strs.add(String.format("%02x",
					Integer.valueOf(random.nextInt(256))));
		}

		String randomStr = String.join("", strs);
		String refName = "branch";
		for (long i = 0; i < 2; i++) {
			RefUpdate ru = refDb.newUpdate(refName, false);
			ru.setNewObjectId(i % 2 == 0 ? aId : bId);
			ru.setForceUpdate(true);
			// Only write a large string in the first table, so it becomes much larger
			// than the second, and the result is not autocompacted.
			ru.setRefLogMessage(i == 0 ? randomStr : "short", false);
			ru.setRefLogIdent(person);

			RefUpdate.Result res = ru.update();
			assertTrue(res == Result.NEW || res == FORCED);
		}

		assertEquals(refDb.exactRef(refName).getObjectId(), bId);
		assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
		refDb.compactFully();
		assertEquals(refDb.exactRef(refName).getObjectId(), bId);
		assertTrue(randomStr.equals(refDb.getReflogReader(refName).getReverseEntry(1).getComment()));
	}

	@Test
	public void reftableRefsStorageClass() throws IOException {
		Ref b = db.exactRef("refs/heads/b");
		assertEquals(Ref.Storage.PACKED, b.getStorage());
	}

	private RefUpdate updateRef(String name) throws IOException {
		final RefUpdate ref = db.updateRef(name);
		ref.setNewObjectId(db.resolve(Constants.HEAD));
		return ref;
	}

	private void writeSymref(String src, String dst) throws IOException {
		RefUpdate u = db.updateRef(src);
		switch (u.link(dst)) {
		case NEW:
		case FORCED:
		case NO_CHANGE:
			break;
		default:
			fail("link " + src + " to " + dst);
		}
	}
}
