Skip to content

Commit

Permalink
Merge pull request #1022 from gitblit/974-in-browser-doc-editor
Browse files Browse the repository at this point in the history
Support for editing documents in the browser #974
  • Loading branch information
paulsputer committed Mar 28, 2016
2 parents 86401c3 + 795ce27 commit 33f3580
Show file tree
Hide file tree
Showing 27 changed files with 1,149 additions and 153 deletions.
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

0 comments on commit 33f3580

Please sign in to comment.