Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

974 in browser doc editor #1022

Merged
merged 4 commits into from
Mar 28, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "src/main/distrib/data/gitignore"]
path = src/main/distrib/data/gitignore
url = https://github.com/github/gitignore.git
[submodule "src/main/js/prosemirror"]
path = src/main/js/prosemirror
url = https://github.com/ProseMirror/prosemirror.git
17 changes: 17 additions & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1056,4 +1056,21 @@
<mx:install />
</target>


<!--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Build Gitblit UI via npm
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-->
<target name="buildUI" description="Build Gitblit UI via npm">
<exec executable="npm" dir="src/main/js/" failonerror="true" vmlauncher="false" searchpath="true" >
<arg value="install" />
</exec>

<exec executable="npm" dir="src/main/js/" failonerror="true" vmlauncher="false" searchpath="true" >
<arg value="run" />
<arg value="build" />
</exec>
</target>

</project>
109 changes: 7 additions & 102 deletions src/main/java/com/gitblit/tickets/BranchTicketService.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
Expand All @@ -31,21 +30,17 @@
import java.util.concurrent.atomic.AtomicLong;

import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.events.RefsChangedEvent;
import org.eclipse.jgit.events.RefsChangedListener;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
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.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
Expand Down Expand Up @@ -338,7 +333,7 @@ private void writeTicketsFile(Repository db, String file, String content, String
Set<String> ignorePaths = new HashSet<String>();
ignorePaths.add(file);

for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) {
builder.add(entry);
}

Expand Down Expand Up @@ -804,7 +799,7 @@ private DirCache createIndex(Repository db, long ticketId, Change change)
}
}

for (DirCacheEntry entry : getTreeEntries(db, ignorePaths)) {
for (DirCacheEntry entry : JGitUtils.getTreeEntries(db, BRANCH, ignorePaths)) {
builder.add(entry);
}

Expand All @@ -816,108 +811,18 @@ private DirCache createIndex(Repository db, long ticketId, Change change)
return newIndex;
}

/**
* Returns all tree entries that do not match the ignore paths.
*
* @param db
* @param ignorePaths
* @param dcBuilder
* @throws IOException
*/
private List<DirCacheEntry> getTreeEntries(Repository db, Collection<String> ignorePaths) throws IOException {
List<DirCacheEntry> list = new ArrayList<DirCacheEntry>();
TreeWalk tw = null;
try {
ObjectId treeId = db.resolve(BRANCH + "^{tree}");
if (treeId == null) {
// branch does not exist yet, could be migrating tickets
return list;
}
tw = new TreeWalk(db);
int hIdx = tw.addTree(treeId);
tw.setRecursive(true);

while (tw.next()) {
String path = tw.getPathString();
CanonicalTreeParser hTree = null;
if (hIdx != -1) {
hTree = tw.getTree(hIdx, CanonicalTreeParser.class);
}
if (!ignorePaths.contains(path)) {
// add all other tree entries
if (hTree != null) {
final DirCacheEntry entry = new DirCacheEntry(path);
entry.setObjectId(hTree.getEntryObjectId());
entry.setFileMode(hTree.getEntryFileMode());
list.add(entry);
}
}
}
} finally {
if (tw != null) {
tw.close();
}
}
return list;
}

private boolean commitIndex(Repository db, DirCache index, String author, String message) throws IOException, ConcurrentRefUpdateException {
final boolean forceCommit = true;
boolean success = false;

ObjectId headId = db.resolve(BRANCH + "^{commit}");
if (headId == null) {
// create the branch
createTicketsBranch(db);
headId = db.resolve(BRANCH + "^{commit}");
}
ObjectInserter odi = db.newObjectInserter();
try {
// Create the in-memory index of the new/updated ticket
ObjectId indexTreeId = index.writeTree(odi);

// Create a commit object
PersonIdent ident = new PersonIdent(author, "gitblit@localhost");
CommitBuilder commit = new CommitBuilder();
commit.setAuthor(ident);
commit.setCommitter(ident);
commit.setEncoding(Constants.ENCODING);
commit.setMessage(message);
commit.setParentId(headId);
commit.setTreeId(indexTreeId);

// Insert the commit into the repository
ObjectId commitId = odi.insert(commit);
odi.flush();

RevWalk revWalk = new RevWalk(db);
try {
RevCommit revCommit = revWalk.parseCommit(commitId);
RefUpdate ru = db.updateRef(BRANCH);
ru.setNewObjectId(commitId);
ru.setExpectedOldObjectId(headId);
ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
Result rc = ru.forceUpdate();
switch (rc) {
case NEW:
case FORCED:
case FAST_FORWARD:
success = true;
break;
case REJECTED:
case LOCK_FAILURE:
throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD,
ru.getRef(), rc);
default:
throw new JGitInternalException(MessageFormat.format(
JGitText.get().updatingRefFailed, BRANCH, commitId.toString(),
rc));
}
} finally {
revWalk.close();
}
} finally {
odi.close();
}

success = JGitUtils.commitIndex(db, BRANCH, index, headId, forceCommit, author, "gitblit@localhost", message);

return success;
}

Expand Down
148 changes: 148 additions & 0 deletions src/main/java/com/gitblit/utils/JGitUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
Expand All @@ -36,16 +37,21 @@
import org.eclipse.jgit.api.FetchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.diff.DiffEntry;
import org.eclipse.jgit.diff.DiffEntry.ChangeType;
import org.eclipse.jgit.diff.DiffFormatter;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.StopWalkException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.BlobBasedConfig;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
Expand All @@ -63,6 +69,7 @@
import org.eclipse.jgit.lib.TreeFormatter;
import org.eclipse.jgit.merge.MergeStrategy;
import org.eclipse.jgit.merge.RecursiveMerger;
import org.eclipse.jgit.merge.ThreeWayMerger;
import org.eclipse.jgit.revwalk.RevBlob;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
Expand All @@ -75,6 +82,7 @@
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.FetchResult;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.OrTreeFilter;
Expand Down Expand Up @@ -2597,4 +2605,144 @@ public static String getLfsRepositoryUrl(String baseURL, String repositoryName,
+ "objects/" + oid;

}

/**
* Returns all tree entries that do not match the ignore paths.
*
* @param db
* @param ignorePaths
* @param dcBuilder
* @throws IOException
*/
public static List<DirCacheEntry> getTreeEntries(Repository db, String branch, Collection<String> ignorePaths) throws IOException {
List<DirCacheEntry> list = new ArrayList<DirCacheEntry>();
TreeWalk tw = null;
try {
ObjectId treeId = db.resolve(branch + "^{tree}");
if (treeId == null) {
// branch does not exist yet
return list;
}
tw = new TreeWalk(db);
int hIdx = tw.addTree(treeId);
tw.setRecursive(true);

while (tw.next()) {
String path = tw.getPathString();
CanonicalTreeParser hTree = null;
if (hIdx != -1) {
hTree = tw.getTree(hIdx, CanonicalTreeParser.class);
}
if (!ignorePaths.contains(path)) {
// add all other tree entries
if (hTree != null) {
final DirCacheEntry entry = new DirCacheEntry(path);
entry.setObjectId(hTree.getEntryObjectId());
entry.setFileMode(hTree.getEntryFileMode());
list.add(entry);
}
}
}
} finally {
if (tw != null) {
tw.close();
}
}
return list;
}

public static boolean commitIndex(Repository db, String branch, DirCache index,
ObjectId parentId, boolean forceCommit,
String author, String authorEmail, String message) throws IOException, ConcurrentRefUpdateException {
boolean success = false;

ObjectId headId = db.resolve(branch + "^{commit}");
ObjectId baseId = parentId;
if (baseId == null || headId == null) { return false; }

ObjectInserter odi = db.newObjectInserter();
try {
// Create the in-memory index of the new/updated ticket
ObjectId indexTreeId = index.writeTree(odi);

// Create a commit object
PersonIdent ident = new PersonIdent(author, authorEmail);

if (forceCommit == false) {
ThreeWayMerger merger = MergeStrategy.RECURSIVE.newMerger(db, true);
merger.setObjectInserter(odi);
merger.setBase(baseId);
boolean mergeSuccess = merger.merge(indexTreeId, headId);

if (mergeSuccess) {
indexTreeId = merger.getResultTreeId();
} else {
//Manual merge required
return false;
}
}

CommitBuilder commit = new CommitBuilder();
commit.setAuthor(ident);
commit.setCommitter(ident);
commit.setEncoding(com.gitblit.Constants.ENCODING);
commit.setMessage(message);
commit.setParentId(headId);
commit.setTreeId(indexTreeId);

// Insert the commit into the repository
ObjectId commitId = odi.insert(commit);
odi.flush();

RevWalk revWalk = new RevWalk(db);
try {
RevCommit revCommit = revWalk.parseCommit(commitId);
RefUpdate ru = db.updateRef(branch);
ru.setForceUpdate(forceCommit);
ru.setNewObjectId(commitId);
ru.setExpectedOldObjectId(headId);
ru.setRefLogMessage("commit: " + revCommit.getShortMessage(), false);
Result rc = ru.update();

switch (rc) {
case NEW:
case FORCED:
case FAST_FORWARD:
success = true;
break;
case REJECTED:
case LOCK_FAILURE:
throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD,
ru.getRef(), rc);
default:
throw new JGitInternalException(MessageFormat.format(
JGitText.get().updatingRefFailed, branch, commitId.toString(),
rc));
}
} finally {
revWalk.close();
}
} finally {
odi.close();
}
return success;
}

/**
* Returns true if the commit identified by commitId is at the tip of it's branch.
*
* @param repository
* @param commitId
* @return true if the given commit is the tip
*/
public static boolean isTip(Repository repository, String commitId) {
try {
RefModel tip = getBranch(repository, commitId);
return (tip != null);
} catch (Exception e) {
LOGGER.error("Failed to determine isTip", e);
}
return false;
}

}
2 changes: 2 additions & 0 deletions src/main/java/com/gitblit/wicket/GitBlitWebApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import com.gitblit.wicket.pages.ComparePage;
import com.gitblit.wicket.pages.DocPage;
import com.gitblit.wicket.pages.DocsPage;
import com.gitblit.wicket.pages.EditFilePage;
import com.gitblit.wicket.pages.EditMilestonePage;
import com.gitblit.wicket.pages.EditRepositoryPage;
import com.gitblit.wicket.pages.EditTicketPage;
Expand Down Expand Up @@ -230,6 +231,7 @@ public void init() {
// setup the markup document urls
mount("/docs", DocsPage.class, "r", "h");
mount("/doc", DocPage.class, "r", "h", "f");
mount("/editfile", EditFilePage.class, "r", "h", "f");

// federation urls
mount("/proposal", ReviewProposalPage.class, "t");
Expand Down