James Moger
2014-03-08 c134a0c3f2440a09c5b8c8c6837c95aba3d4f84f
Move Gitblit branches to refs/meta/gitblit
8 files modified
177 ■■■■■ changed files
releases.moxie 1 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/Constants.java 2 ●●● patch | view | raw | blame | history
src/main/java/com/gitblit/service/LuceneService.java 8 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/tickets/BranchTicketService.java 28 ●●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/utils/RefLogUtils.java 118 ●●●● patch | view | raw | blame | history
src/main/java/com/gitblit/wicket/panels/RefsPanel.java 6 ●●●● patch | view | raw | blame | history
src/site/tickets_replication.mkd 12 ●●●● patch | view | raw | blame | history
src/site/tickets_setup.mkd 2 ●●● patch | view | raw | blame | history
releases.moxie
@@ -54,6 +54,7 @@
    - Serve repositories on both /r and /git, displaying /r because it is shorter
    - Eliminate HEAD from the blob, blame, and tree pages. That assumed a resource was available in HEAD and it may not be.
    - Eliminate Gravatar profile linking.
    - Moved Gitblit reflog from refs/gitblit/reflog to refs/meta/gitblit/reflog
    - Updated Spanish translation
    - Updated Simplified Chinese translation
    - Updated Dutch translation
src/main/java/com/gitblit/Constants.java
@@ -100,7 +100,7 @@
    public static final String HEAD = "HEAD";
    public static final String R_GITBLIT = "refs/gitblit/";
    public static final String R_META = "refs/meta/";
    public static final String R_HEADS = "refs/heads/";
src/main/java/com/gitblit/service/LuceneService.java
@@ -476,8 +476,8 @@
                        && branch.equals(defaultBranch)) {
                    // indexing "default" branch
                    indexBranch = true;
                } else if (branch.getName().startsWith(com.gitblit.Constants.R_GITBLIT)) {
                    // skip Gitblit internal branches
                } else if (branch.getName().startsWith(com.gitblit.Constants.R_META)) {
                    // skip internal meta branches
                    indexBranch = false;
                } else {
                    // normal explicit branch check
@@ -807,8 +807,8 @@
                        && branch.equals(defaultBranch)) {
                    // indexing "default" branch
                    indexBranch = true;
                } else if (branch.getName().startsWith(com.gitblit.Constants.R_GITBLIT)) {
                    // ignore internal Gitblit branches
                } else if (branch.getName().startsWith(com.gitblit.Constants.R_META)) {
                    // ignore internal meta branches
                    indexBranch = false;
                } else {
                    // normal explicit branch check
src/main/java/com/gitblit/tickets/BranchTicketService.java
@@ -43,6 +43,8 @@
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;
@@ -80,7 +82,7 @@
 */
public class BranchTicketService extends ITicketService implements RefsChangedListener {
    public static final String BRANCH = "refs/gitblit/tickets";
    public static final String BRANCH = "refs/meta/gitblit/tickets";
    private static final String JOURNAL = "journal.json";
@@ -193,10 +195,32 @@
     * @return a refmodel for the gitblit tickets branch or null
     */
    private RefModel getTicketsBranch(Repository db) {
        List<RefModel> refs = JGitUtils.getRefs(db, Constants.R_GITBLIT);
        List<RefModel> refs = JGitUtils.getRefs(db, "refs/");
        Ref oldRef = null;
        for (RefModel ref : refs) {
            if (ref.reference.getName().equals(BRANCH)) {
                return ref;
            } else if (ref.reference.getName().equals("refs/gitblit/tickets")) {
                oldRef = ref.reference;
            }
        }
        if (oldRef != null) {
            // rename old ref to refs/meta/gitblit/tickets
            RefRename cmd;
            try {
                cmd = db.renameRef(oldRef.getName(), BRANCH);
                cmd.setRefLogIdent(new PersonIdent("Gitblit", "gitblit@localhost"));
                cmd.setRefLogMessage("renamed " + oldRef.getName() + " => " + BRANCH);
                Result res = cmd.rename();
                switch (res) {
                case RENAMED:
                    log.info(db.getDirectory() + " " + cmd.getRefLogMessage());
                    return getTicketsBranch(db);
                default:
                    log.error("failed to rename " + oldRef.getName() + " => " + BRANCH + " (" + res.name() + ")");
                }
            } catch (IOException e) {
                log.error("failed to rename tickets branch", e);
            }
        }
        return null;
src/main/java/com/gitblit/utils/RefLogUtils.java
@@ -72,7 +72,7 @@
 */
public class RefLogUtils {
    private static final String GB_REFLOG = "refs/gitblit/reflog";
    private static final String GB_REFLOG = "refs/meta/gitblit/reflog";
    private static final Logger LOGGER = LoggerFactory.getLogger(RefLogUtils.class);
@@ -122,32 +122,34 @@
     * @return a refmodel for the reflog branch or null
     */
    public static RefModel getRefLogBranch(Repository repository) {
        List<RefModel> refs = JGitUtils.getRefs(repository, com.gitblit.Constants.R_GITBLIT);
        RefModel pushLog = null;
        final String GB_PUSHES = "refs/gitblit/pushes";
        List<RefModel> refs = JGitUtils.getRefs(repository, "refs/");
        Ref oldRef = null;
        for (RefModel ref : refs) {
            if (ref.reference.getName().equals(GB_REFLOG)) {
                return ref;
            } else if (ref.reference.getName().equals(GB_PUSHES)) {
                pushLog = ref;
            } else if (ref.reference.getName().equals("refs/gitblit/reflog")) {
                oldRef = ref.reference;
            } else if (ref.reference.getName().equals("refs/gitblit/pushes")) {
                oldRef = ref.reference;
            }
        }
        if (pushLog != null) {
            // rename refs/gitblit/pushes to refs/gitblit/reflog
        if (oldRef != null) {
            // rename old ref to refs/meta/gitblit/reflog
            RefRename cmd;
            try {
                cmd = repository.renameRef(GB_PUSHES, GB_REFLOG);
                cmd = repository.renameRef(oldRef.getName(), GB_REFLOG);
                cmd.setRefLogIdent(new PersonIdent("Gitblit", "gitblit@localhost"));
                cmd.setRefLogMessage("renamed " + GB_PUSHES + " => " + GB_REFLOG);
                cmd.setRefLogMessage("renamed " + oldRef.getName() + " => " + GB_REFLOG);
                Result res = cmd.rename();
                switch (res) {
                case RENAMED:
                    LOGGER.info(repository.getDirectory() + " " + cmd.getRefLogMessage());
                    return getRefLogBranch(repository);
                default:
                    LOGGER.error("failed to rename " + GB_PUSHES + " => " + GB_REFLOG + " (" + res.name() + ")");
                    LOGGER.error("failed to rename " + oldRef.getName() + " => " + GB_REFLOG + " (" + res.name() + ")");
                }
            } catch (IOException e) {
                LOGGER.error("failed to rename pushlog", e);
                LOGGER.error("failed to rename reflog", e);
            }
        }
        return null;
@@ -241,7 +243,7 @@
            ObjectId headId = repository.resolve(GB_REFLOG + "^{commit}");
            ObjectInserter odi = repository.newObjectInserter();
            try {
                // Create the in-memory index of the push log entry
                // Create the in-memory index of the reflog log entry
                DirCache index = createIndex(repository, headId, commands);
                ObjectId indexTreeId = index.writeTree(odi);
@@ -304,7 +306,7 @@
    }
    /**
     * Creates an in-memory index of the push log entry.
     * Creates an in-memory index of the reflog entry.
     *
     * @param repo
     * @param headId
@@ -428,8 +430,8 @@
     * @param minimumDate
     * @param offset
     * @param maxCount
     *             if < 0, all pushes are returned.
     * @return a list of push log entries
     *             if < 0, all entries are returned.
     * @return a list of reflog entries
     */
    public static List<RefLogEntry> getRefLog(String repositoryName, Repository repository,
            Date minimumDate, int offset, int maxCount) {
@@ -507,31 +509,31 @@
    }
    /**
     * Returns the list of pushes separated by ref (e.g. each ref has it's own
     * PushLogEntry object).
     * Returns the list of entries organized by ref (e.g. each ref has it's own
     * RefLogEntry object).
     *
     * @param repositoryName
     * @param repository
     * @param maxCount
     * @return a list of push log entries separated by ref
     * @return a list of reflog entries separated by ref
     */
    public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository, int maxCount) {
        return getLogByRef(repositoryName, repository, 0, maxCount);
    }
    /**
     * Returns the list of pushes separated by ref (e.g. each ref has it's own
     * PushLogEntry object).
     * Returns the list of entries organized by ref (e.g. each ref has it's own
     * RefLogEntry object).
     *
     * @param repositoryName
     * @param repository
     * @param offset
     * @param maxCount
     * @return a list of push log entries separated by ref
     * @return a list of reflog entries separated by ref
     */
    public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository,  int offset,
            int maxCount) {
        // break the push log into ref push logs and then merge them back into a list
        // break the reflog into ref entries and then merge them back into a list
        Map<String, List<RefLogEntry>> refMap = new HashMap<String, List<RefLogEntry>>();
        List<RefLogEntry> refLog = getRefLog(repositoryName, repository, offset, maxCount);
        for (RefLogEntry entry : refLog) {
@@ -543,10 +545,10 @@
                // construct new ref-specific ref change entry
                RefLogEntry refChange;
                if (entry instanceof DailyLogEntry) {
                    // simulated push log from commits grouped by date
                    // simulated reflog from commits grouped by date
                    refChange = new DailyLogEntry(entry.repository, entry.date);
                } else {
                    // real push log entry
                    // real reflog entry
                    refChange = new RefLogEntry(entry.repository, entry.date, entry.user);
                }
                refChange.updateRef(ref, entry.getChangeType(ref), entry.getOldId(ref), entry.getNewId(ref));
@@ -577,33 +579,32 @@
     * @return a list of ref log entries separated by ref
     */
    public static List<RefLogEntry> getLogByRef(String repositoryName, Repository repository,  Date minimumDate) {
        // break the push log into ref push logs and then merge them back into a list
        // break the reflog into refs and then merge them back into a list
        Map<String, List<RefLogEntry>> refMap = new HashMap<String, List<RefLogEntry>>();
        List<RefLogEntry> pushes = getRefLog(repositoryName, repository, minimumDate);
        for (RefLogEntry push : pushes) {
            for (String ref : push.getChangedRefs()) {
        List<RefLogEntry> entries = getRefLog(repositoryName, repository, minimumDate);
        for (RefLogEntry entry : entries) {
            for (String ref : entry.getChangedRefs()) {
                if (!refMap.containsKey(ref)) {
                    refMap.put(ref, new ArrayList<RefLogEntry>());
                }
                // construct new ref-specific push log entry
                RefLogEntry refPush = new RefLogEntry(push.repository, push.date, push.user);
                refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
                refPush.addCommits(push.getCommits(ref));
                // construct new ref-specific log entry
                RefLogEntry refPush = new RefLogEntry(entry.repository, entry.date, entry.user);
                refPush.updateRef(ref, entry.getChangeType(ref), entry.getOldId(ref), entry.getNewId(ref));
                refPush.addCommits(entry.getCommits(ref));
                refMap.get(ref).add(refPush);
            }
        }
        // merge individual ref pushes into master list
        List<RefLogEntry> refPushLog = new ArrayList<RefLogEntry>();
        for (List<RefLogEntry> refPush : refMap.values()) {
            refPushLog.addAll(refPush);
        // merge individual ref entries into master list
        List<RefLogEntry> refLog = new ArrayList<RefLogEntry>();
        for (List<RefLogEntry> entry : refMap.values()) {
            refLog.addAll(entry);
        }
        // sort ref push log
        Collections.sort(refPushLog);
        Collections.sort(refLog);
        return refPushLog;
        return refLog;
    }
    /**
@@ -614,7 +615,7 @@
     * @param minimumDate
     * @param offset
     * @param maxCount
     *             if < 0, all pushes are returned.
     *             if < 0, all entries are returned.
     * @param the timezone to use when aggregating commits by date
     * @return a list of grouped commit log entries
     */
@@ -703,7 +704,7 @@
    /**
     * Returns the list of commits separated by ref (e.g. each ref has it's own
     * PushLogEntry object for each day).
     * RefLogEntry object for each day).
     *
     * @param repositoryName
     * @param repository
@@ -713,36 +714,35 @@
     */
    public static List<DailyLogEntry> getDailyLogByRef(String repositoryName, Repository repository,
            Date minimumDate, TimeZone timezone) {
        // break the push log into ref push logs and then merge them back into a list
        // break the reflog into ref entries and then merge them back into a list
        Map<String, List<DailyLogEntry>> refMap = new HashMap<String, List<DailyLogEntry>>();
        List<DailyLogEntry> pushes = getDailyLog(repositoryName, repository, minimumDate, 0, -1, timezone);
        for (DailyLogEntry push : pushes) {
            for (String ref : push.getChangedRefs()) {
        List<DailyLogEntry> entries = getDailyLog(repositoryName, repository, minimumDate, 0, -1, timezone);
        for (DailyLogEntry entry : entries) {
            for (String ref : entry.getChangedRefs()) {
                if (!refMap.containsKey(ref)) {
                    refMap.put(ref, new ArrayList<DailyLogEntry>());
                }
                // construct new ref-specific push log entry
                DailyLogEntry refPush = new DailyLogEntry(push.repository, push.date, push.user);
                refPush.updateRef(ref, push.getChangeType(ref), push.getOldId(ref), push.getNewId(ref));
                refPush.addCommits(push.getCommits(ref));
                refMap.get(ref).add(refPush);
                // construct new ref-specific log entry
                DailyLogEntry refEntry = new DailyLogEntry(entry.repository, entry.date, entry.user);
                refEntry.updateRef(ref, entry.getChangeType(ref), entry.getOldId(ref), entry.getNewId(ref));
                refEntry.addCommits(entry.getCommits(ref));
                refMap.get(ref).add(refEntry);
            }
        }
        // merge individual ref pushes into master list
        List<DailyLogEntry> refPushLog = new ArrayList<DailyLogEntry>();
        for (List<DailyLogEntry> refPush : refMap.values()) {
            for (DailyLogEntry entry : refPush) {
        // merge individual ref entries into master list
        List<DailyLogEntry> refLog = new ArrayList<DailyLogEntry>();
        for (List<DailyLogEntry> refEntry : refMap.values()) {
            for (DailyLogEntry entry : refEntry) {
                if (entry.getCommitCount() > 0) {
                    refPushLog.add(entry);
                    refLog.add(entry);
                }
            }
        }
        // sort ref push log
        Collections.sort(refPushLog);
        Collections.sort(refLog);
        return refPushLog;
        return refLog;
    }
}
src/main/java/com/gitblit/wicket/panels/RefsPanel.java
@@ -173,11 +173,11 @@
                    // codereview refs
                    linkClass = CommitPage.class;
                    cssClass = "otherRef";
                } else if (name.startsWith(com.gitblit.Constants.R_GITBLIT)) {
                    // gitblit refs
                } else if (name.startsWith(com.gitblit.Constants.R_META)) {
                    // internal meta refs
                    linkClass = LogPage.class;
                    cssClass = "otherRef";
                    name = name.substring(com.gitblit.Constants.R_GITBLIT.length());
                    name = name.substring(com.gitblit.Constants.R_META.length());
                }
                Component c = new LinkPanel("refName", null, name, linkClass,
src/site/tickets_replication.mkd
@@ -23,7 +23,7 @@
#### Ticket Replication
Gitblit supports ticket replication for a couple of scenarios with the *BranchTicketService*.  This requires that the Gitblit instance receiving the ticket data be configured for the *BranchTicketService*.  Likewise, the source of the ticket data must be a repository that has ticket data persisted using the *BranchTicketService*.
##### Manually Pushing refs/gitblit/tickets
##### Manually Pushing refs/meta/gitblit/tickets
Let's say you wanted to create a perfect clone of the Gitblit repository hosted at https://dev.gitblit.com in your own Gitblit instance.  We'll use this repository as an example because it is configured for the *BranchTicketService*.
@@ -41,7 +41,7 @@
If your push was successful you should have a new repository with the entire official Gitblit tickets data.
##### Mirroring refs/gitblit/tickets
##### Mirroring refs/meta/gitblit/tickets
Gitblit 1.4.0 introduces a mirroring service.  This is not the same as the federation feature - although there are similarities.
@@ -55,16 +55,16 @@
4. After you have indexed the repository, Gitblit will take over and incrementally update your tickets data on each fetch.
#### Advanced Administration
Repository owners or Gitblit administrators have the option of manually editing ticket data.  To do this you must fetch and checkout the `refs/gitblit/tickets` ref.  This orphan branch is where ticket data is stored.  You may then use a text editor to **carefully** manipulate journals and push your changes back upstream.  I recommend using a JSON validation tool to ensure your changes are valid JSON.
Repository owners or Gitblit administrators have the option of manually editing ticket data.  To do this you must fetch and checkout the `refs/meta/gitblit/tickets` ref.  This orphan branch is where ticket data is stored.  You may then use a text editor to **carefully** manipulate journals and push your changes back upstream.  I recommend using a JSON validation tool to ensure your changes are valid JSON.
    git fetch origin refs/gitblit/tickets
    git fetch origin refs/meta/gitblit/tickets
    git checkout -B tix FETCH_HEAD
    ...fix data...
    git add .
    git commit
    git push origin HEAD:refs/gitblit/tickets
    git push origin HEAD:refs/meta/gitblit/tickets
Gitblit will identify the incoming `refs/gitblit/tickets` ref update and will incrementally index the changed tickets OR, if the update is non-fast-forward, all tickets on that branch will be reindexed.
Gitblit will identify the incoming `refs/meta/gitblit/tickets` ref update and will incrementally index the changed tickets OR, if the update is non-fast-forward, all tickets on that branch will be reindexed.
### RedisTicketService
src/site/tickets_setup.mkd
@@ -20,7 +20,7 @@
    tickets.service = com.gitblit.tickets.BranchTicketService
Your ticket journals are persisted to `id/{shard}/{id}/journal.json`.  These journals are stored on an orphan branch, `refs/gitblit/tickets`, within your repository.  This allows you to easily clone your entire ticket history to client working copies or to mirrors.
Your ticket journals are persisted to `id/{shard}/{id}/journal.json`.  These journals are stored on an orphan branch, `refs/meta/gitblit/tickets`, within your repository.  This allows you to easily clone your entire ticket history to client working copies or to mirrors.
#### Redis Ticket Service