* [EGIT PATCH 0/9] Repository change listeners
@ 2008-07-10 22:40 Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Robin Rosenberg
2008-07-11 5:26 ` [EGIT PATCH 0/9] Repository change listeners Shawn O. Pearce
0 siblings, 2 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
We want to make the UI react on changes to the repo, but the parts
of the code that makes the changes doesn't know who wants to react
on them. This adds a publish-subcribe mechanism, including detection
of externally made changes, e.g. by C Git.
-- robin
Robin Rosenberg (9):
Create a listener structure for changes to refs and index
Cached modification times for symbolic refs too
Connect the history page to the refs update subscription mechanism
Add a method to listen to changes in any repository
Add a job to periodically scan for repository changes
Change GitHistoryPage to listen on any repository.
Add a job to refresh projects when the index changes.
Make git dectected changes depend on the automatic refresh setting
Attach the resource decorator to the repository change event
mechanism
.../src/org/spearce/egit/ui/Activator.java | 155 ++++++++++++++++++++
.../internal/decorators/GitResourceDecorator.java | 29 ++++-
.../egit/ui/internal/history/GitHistoryPage.java | 43 +++++-
.../src/org/spearce/jgit/lib/GitIndex.java | 3 +
.../org/spearce/jgit/lib/IndexChangedEvent.java | 55 +++++++
.../src/org/spearce/jgit/lib/RefDatabase.java | 63 ++++++---
.../src/org/spearce/jgit/lib/RefsChangedEvent.java | 55 +++++++
.../src/org/spearce/jgit/lib/Repository.java | 74 ++++++++++
.../org/spearce/jgit/lib/RepositoryAdapter.java | 54 +++++++
.../spearce/jgit/lib/RepositoryChangedEvent.java | 64 ++++++++
.../org/spearce/jgit/lib/RepositoryListener.java | 63 ++++++++
11 files changed, 635 insertions(+), 23 deletions(-)
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
^ permalink raw reply [flat|nested] 19+ messages in thread
* [EGIT PATCH 1/9] Create a listener structure for changes to refs and index
2008-07-10 22:40 [EGIT PATCH 0/9] Repository change listeners Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 2/9] Cached modification times for symbolic refs too Robin Rosenberg
2008-07-11 4:22 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Shawn O. Pearce
2008-07-11 5:26 ` [EGIT PATCH 0/9] Repository change listeners Shawn O. Pearce
1 sibling, 2 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
This version does not tell you which refs have changed, nor
what changes have happened. There is not scanning for externally
initiated changes either, though such changes can be found when
a JGit client wants to read index or refs information.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../egit/ui/internal/history/GitHistoryPage.java | 31 +++++++++-
.../src/org/spearce/jgit/lib/GitIndex.java | 3 +
.../org/spearce/jgit/lib/IndexChangedEvent.java | 55 +++++++++++++++++
.../src/org/spearce/jgit/lib/RefDatabase.java | 17 +++++
.../src/org/spearce/jgit/lib/RefsChangedEvent.java | 55 +++++++++++++++++
.../src/org/spearce/jgit/lib/Repository.java | 41 +++++++++++++
.../org/spearce/jgit/lib/RepositoryAdapter.java | 54 ++++++++++++++++
.../spearce/jgit/lib/RepositoryChangedEvent.java | 64 ++++++++++++++++++++
.../org/spearce/jgit/lib/RepositoryListener.java | 63 +++++++++++++++++++
9 files changed, 382 insertions(+), 1 deletions(-)
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
index 6b55185..7e2f726 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
@@ -61,7 +61,10 @@ import org.spearce.egit.ui.UIIcons;
import org.spearce.egit.ui.UIPreferences;
import org.spearce.egit.ui.UIText;
import org.spearce.jgit.lib.AnyObjectId;
+import org.spearce.jgit.lib.IndexChangedEvent;
+import org.spearce.jgit.lib.RefsChangedEvent;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.RepositoryListener;
import org.spearce.jgit.revplot.PlotCommit;
import org.spearce.jgit.revwalk.RevCommit;
import org.spearce.jgit.revwalk.RevFlag;
@@ -73,7 +76,7 @@ import org.spearce.jgit.treewalk.filter.PathFilterGroup;
import org.spearce.jgit.treewalk.filter.TreeFilter;
/** Graphical commit history viewer. */
-public class GitHistoryPage extends HistoryPage {
+public class GitHistoryPage extends HistoryPage implements RepositoryListener {
private static final String PREF_COMMENT_WRAP = UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP;
private static final String PREF_COMMENT_FILL = UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_FILL;
@@ -230,6 +233,32 @@ public class GitHistoryPage extends HistoryPage {
layout();
}
+ private Runnable refschangedRunnable;
+
+ public void refsChanged(final RefsChangedEvent e) {
+ if (getControl().isDisposed())
+ return;
+
+ synchronized (this) {
+ if (refschangedRunnable == null) {
+ refschangedRunnable = new Runnable() {
+ public void run() {
+ if (!getControl().isDisposed()) {
+ Activator.trace("Executing async repository changed event");
+ refschangedRunnable = null;
+ inputSet();
+ }
+ }
+ };
+ getControl().getDisplay().asyncExec(refschangedRunnable);
+ }
+ }
+ }
+
+ public void indexChanged(final IndexChangedEvent e) {
+ // We do not use index information here now
+ }
+
private void finishContextMenu() {
popupMgr.add(new Separator());
popupMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
index 5be404e..c7a4402 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
@@ -146,6 +146,7 @@ public class GitIndex {
public void rereadIfNecessary() throws IOException {
if (cacheFile.exists() && cacheFile.lastModified() != lastCacheTime) {
read();
+ db.fireIndexChanged();
}
}
@@ -269,6 +270,8 @@ public class GitIndex {
"Could not rename temporary index file to index");
changed = false;
statDirty = false;
+ lastCacheTime = cacheFile.lastModified();
+ db.fireIndexChanged();
} finally {
if (!lock.delete())
throw new IOException(
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
new file mode 100644
index 0000000..30a40d1
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about a changed Git index to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class IndexChangedEvent extends RepositoryChangedEvent {
+ IndexChangedEvent(final Repository repository) {
+ super(repository);
+ }
+
+ @Override
+ public String toString() {
+ return "IndexChangedEvent[" + getRepository() + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
index 9e3e020..4be33b8 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
@@ -81,6 +81,10 @@ class RefDatabase {
private long packedRefsLength;
+ long lastRefModification;
+
+ long lastNotifiedRefModification;
+
RefDatabase(final Repository r) {
db = r;
gitDir = db.getDirectory();
@@ -132,6 +136,8 @@ class RefDatabase {
void stored(final String name, final ObjectId id, final long time) {
looseRefs.put(name, new CachedRef(Ref.Storage.LOOSE, name, id, time));
+ setModified();
+ db.fireRefsMaybeChanged();
}
/**
@@ -155,6 +161,12 @@ class RefDatabase {
}
if (!lck.commit())
throw new ObjectWritingException("Unable to write " + name);
+ setModified();
+ db.fireRefsMaybeChanged();
+ }
+
+ void setModified() {
+ lastRefModification = System.currentTimeMillis();
}
Ref readRef(final String partialName) throws IOException {
@@ -192,6 +204,7 @@ class RefDatabase {
readPackedRefs(avail);
readLooseRefs(avail, REFS_SLASH, refsDir);
readOneLooseRef(avail, Constants.HEAD, new File(gitDir, Constants.HEAD));
+ db.fireRefsMaybeChanged();
return avail;
}
@@ -321,6 +334,8 @@ class RefDatabase {
return r != null ? r : new Ref(Ref.Storage.LOOSE, target, null);
}
+ setModified();
+
final ObjectId id;
try {
id = ObjectId.fromString(line);
@@ -378,6 +393,7 @@ class RefDatabase {
packedRefsLastModified = currTime;
packedRefsLength = currLen;
packedRefs = newPackedRefs;
+ setModified();
} catch (FileNotFoundException noPackedRefs) {
// Ignore it and leave the new map empty.
//
@@ -414,4 +430,5 @@ class RefDatabase {
lastModified = mtime;
}
}
+
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
new file mode 100644
index 0000000..c8936c7
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about a changed Git index to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class RefsChangedEvent extends RepositoryChangedEvent {
+ RefsChangedEvent(final Repository repository) {
+ super(repository);
+ }
+
+ @Override
+ public String toString() {
+ return "RefsChangedEvent[" + getRepository() + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 04d9b13..6f78652 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -49,7 +49,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Vector;
import org.spearce.jgit.errors.IncorrectObjectTypeException;
import org.spearce.jgit.errors.RevisionSyntaxException;
@@ -92,6 +94,8 @@ public class Repository {
private GitIndex index;
+ private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
+
/**
* Construct a representation of a Git repository.
*
@@ -1028,4 +1032,41 @@ public class Repository {
public File getWorkDir() {
return getDirectory().getParentFile();
}
+
+ /**
+ * Register a {@link RepositoryListener} which will be notified
+ * when ref changes are detected.
+ *
+ * @param l
+ */
+ public void addRepositoryChangedListener(final RepositoryListener l) {
+ listeners.add(l);
+ }
+
+ /**
+ * Remove a registered {@link RepositoryListener}
+ * @param l
+ */
+ public void removeRepositoryChangedListener(final RepositoryListener l) {
+ listeners.remove(l);
+ }
+
+ void fireRefsMaybeChanged() {
+ if (refs.lastRefModification != refs.lastNotifiedRefModification) {
+ refs.lastNotifiedRefModification = refs.lastRefModification;
+ final RefsChangedEvent event = new RefsChangedEvent(this);
+ for (final RepositoryListener l :
+ listeners.toArray(new RepositoryListener[listeners.size()])) {
+ l.refsChanged(event);
+ }
+ }
+ }
+
+ void fireIndexChanged() {
+ final IndexChangedEvent event = new IndexChangedEvent(this);
+ for (final RepositoryListener l :
+ listeners.toArray(new RepositoryListener[listeners.size()])) {
+ l.indexChanged(event);
+ }
+ }
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
new file mode 100644
index 0000000..d1ff07d
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * A default {@link RepositoryListener} that does nothing except invoke an
+ * optional general method for any repository change.
+ */
+public class RepositoryAdapter implements RepositoryListener {
+
+ public void indexChanged(final IndexChangedEvent e) {
+ // Empty
+ }
+
+ public void refsChanged(final RefsChangedEvent e) {
+ // Empty
+ }
+
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
new file mode 100644
index 0000000..b58df87
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about changed refs to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class RepositoryChangedEvent {
+ private final Repository repository;
+
+ RepositoryChangedEvent(final Repository repository) {
+ this.repository = repository;
+ }
+
+ /**
+ * @return the repository that was changed
+ */
+ public Repository getRepository() {
+ return repository;
+ }
+
+ @Override
+ public String toString() {
+ return "RepositoryChangedEvent[" + repository + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
new file mode 100644
index 0000000..ceb14ce
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * A RepositoryListener gets notification about changes in refs or repository.
+ * <p>
+ * It currently does <em>not</em> get notification about which items are
+ * changed.
+ */
+public interface RepositoryListener {
+ /**
+ * Invoked when a ref changes
+ *
+ * @param e
+ * information about the changes.
+ */
+ void refsChanged(RefsChangedEvent e);
+
+ /**
+ * Invoked when the index changes
+ *
+ * @param e
+ * information about the changes.
+ */
+ void indexChanged(IndexChangedEvent e);
+
+}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 2/9] Cached modification times for symbolic refs too
2008-07-10 22:40 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 3/9] Connect the history page to the refs update subscription mechanism Robin Rosenberg
2008-07-11 4:22 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Shawn O. Pearce
1 sibling, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
We want to detect changes to symbolic refs like HEAD. When HEAD is
redirected to another branch, that's a change even if if the branch
head itself did not change.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/jgit/lib/RefDatabase.java | 48 +++++++++++---------
1 files changed, 27 insertions(+), 21 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
index 4be33b8..17a74e5 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
@@ -71,7 +71,8 @@ class RefDatabase {
private final File refsDir;
- private Map<String, CachedRef> looseRefs;
+ private Map<String, Ref> looseRefs;
+ private Map<String, Long> looseRefsMTime;
private final File packedRefsFile;
@@ -94,7 +95,8 @@ class RefDatabase {
}
void clearCache() {
- looseRefs = new HashMap<String, CachedRef>();
+ looseRefs = new HashMap<String, Ref>();
+ looseRefsMTime = new HashMap<String, Long>();
packedRefs = new HashMap<String, Ref>();
packedRefsLastModified = 0;
packedRefsLength = 0;
@@ -135,7 +137,8 @@ class RefDatabase {
}
void stored(final String name, final ObjectId id, final long time) {
- looseRefs.put(name, new CachedRef(Ref.Storage.LOOSE, name, id, time));
+ looseRefs.put(name, new Ref(Ref.Storage.LOOSE, name, id));
+ looseRefsMTime.put(name, time);
setModified();
db.fireRefsMaybeChanged();
}
@@ -203,7 +206,11 @@ class RefDatabase {
final HashMap<String, Ref> avail = new HashMap<String, Ref>();
readPackedRefs(avail);
readLooseRefs(avail, REFS_SLASH, refsDir);
- readOneLooseRef(avail, Constants.HEAD, new File(gitDir, Constants.HEAD));
+ try {
+ avail.put(Constants.HEAD, readRefBasic(Constants.HEAD, 0));
+ } catch (IOException e) {
+ // ignore here
+ }
db.fireRefsMaybeChanged();
return avail;
}
@@ -231,13 +238,15 @@ class RefDatabase {
final String refName, final File ent) {
// Unchanged and cached? Don't read it again.
//
- CachedRef ref = looseRefs.get(refName);
+ Ref ref = looseRefs.get(refName);
if (ref != null) {
- if (ref.lastModified == ent.lastModified()) {
+ Long cachedlastModified = looseRefsMTime.get(refName);
+ if (cachedlastModified != null && cachedlastModified == ent.lastModified()) {
avail.put(ref.getName(), ref);
return;
}
looseRefs.remove(refName);
+ looseRefsMTime.remove(refName);
}
// Recurse into the directory.
@@ -269,9 +278,9 @@ class RefDatabase {
return;
}
- ref = new CachedRef(Ref.Storage.LOOSE, refName, id, ent
- .lastModified());
+ ref = new Ref(Ref.Storage.LOOSE, refName, id);
looseRefs.put(ref.getName(), ref);
+ looseRefsMTime.put(ref.getName(), ent.lastModified());
avail.put(ref.getName(), ref);
} finally {
in.close();
@@ -297,13 +306,15 @@ class RefDatabase {
// Prefer loose ref to packed ref as the loose
// file can be more up-to-date than a packed one.
//
- CachedRef ref = looseRefs.get(name);
+ Ref ref = looseRefs.get(name);
final File loose = fileForRef(name);
final long mtime = loose.lastModified();
if (ref != null) {
- if (ref.lastModified == mtime)
+ Long cachedlastModified = looseRefsMTime.get(name);
+ if (cachedlastModified != null && cachedlastModified == mtime)
return ref;
looseRefs.remove(name);
+ looseRefsMTime.remove(name);
}
if (mtime == 0) {
@@ -331,6 +342,10 @@ class RefDatabase {
final String target = line.substring("ref: ".length());
final Ref r = readRefBasic(target, depth + 1);
+ Long cachedMtime = looseRefsMTime.get(name);
+ if (cachedMtime != null && cachedMtime != mtime)
+ setModified();
+ looseRefsMTime.put(name, mtime);
return r != null ? r : new Ref(Ref.Storage.LOOSE, target, null);
}
@@ -343,8 +358,9 @@ class RefDatabase {
throw new IOException("Not a ref: " + name + ": " + line);
}
- ref = new CachedRef(Ref.Storage.LOOSE, name, id, mtime);
+ ref = new Ref(Ref.Storage.LOOSE, name, id);
looseRefs.put(name, ref);
+ looseRefsMTime.put(name, mtime);
return ref;
}
@@ -421,14 +437,4 @@ class RefDatabase {
fileLocation), CHAR_ENC));
}
- private static class CachedRef extends Ref {
- final long lastModified;
-
- CachedRef(final Storage st, final String refName, final ObjectId id,
- final long mtime) {
- super(st, refName, id);
- lastModified = mtime;
- }
- }
-
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 3/9] Connect the history page to the refs update subscription mechanism
2008-07-10 22:40 ` [EGIT PATCH 2/9] Cached modification times for symbolic refs too Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Robin Rosenberg
0 siblings, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Now the history page can get updated automatically without polling.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../egit/ui/internal/history/GitHistoryPage.java | 11 ++++++++++-
1 files changed, 10 insertions(+), 1 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
index 7e2f726..418f3b6 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
@@ -168,6 +168,9 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
/** Last HEAD */
private AnyObjectId currentHeadId;
+ /** We need to remember the current repository */
+ private Repository db;
+
/**
* Highlight flag that can be applied to commits to make them stand out.
* <p>
@@ -536,6 +539,9 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
revObjectSelectionProvider.setActiveRepository(null);
cancelRefreshJob();
+ if (db != null)
+ db.removeRepositoryChangedListener(this);
+
if (graph == null)
return false;
@@ -543,7 +549,8 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
if (in == null || in.length == 0)
return false;
- Repository db = null;
+ db = null;
+
final ArrayList<String> paths = new ArrayList<String>(in.length);
for (final IResource r : in) {
final RepositoryMapping map = RepositoryMapping.getMapping(r);
@@ -563,6 +570,8 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
if (db == null)
return false;
+ db.addRepositoryChangedListener(this);
+
final AnyObjectId headId;
try {
headId = db.resolve("HEAD");
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 4/9] Add a method to listen to changes in any repository
2008-07-10 22:40 ` [EGIT PATCH 3/9] Connect the history page to the refs update subscription mechanism Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 5/9] Add a job to periodically scan for repository changes Robin Rosenberg
2008-07-11 4:28 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Shawn O. Pearce
0 siblings, 2 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/jgit/lib/Repository.java | 31 +++++++++++++++++--
1 files changed, 27 insertions(+), 4 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 6f78652..dfa3045 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -95,6 +95,7 @@ public class Repository {
private GitIndex index;
private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
+ static private List<RepositoryListener> allListeners = new Vector<RepositoryListener>(); // thread safe
/**
* Construct a representation of a Git repository.
@@ -1051,12 +1052,32 @@ public class Repository {
listeners.remove(l);
}
+ /**
+ * Register a global {@link RepositoryListener} which will be notified
+ * when a ref changes in any repository are detected.
+ *
+ * @param l
+ */
+ public static void addAnyRepositoryChangedListener(final RepositoryListener l) {
+ allListeners.add(l);
+ }
+
+ /**
+ * Remove a globally registered {@link RepositoryListener}
+ * @param l
+ */
+ public static void removeAnyRepositoryChangedListener(final RepositoryListener l) {
+ allListeners.remove(l);
+ }
+
void fireRefsMaybeChanged() {
if (refs.lastRefModification != refs.lastNotifiedRefModification) {
refs.lastNotifiedRefModification = refs.lastRefModification;
final RefsChangedEvent event = new RefsChangedEvent(this);
- for (final RepositoryListener l :
- listeners.toArray(new RepositoryListener[listeners.size()])) {
+ List<RepositoryListener> all = new ArrayList<RepositoryListener>(
+ listeners);
+ all.addAll(allListeners);
+ for (final RepositoryListener l : all) {
l.refsChanged(event);
}
}
@@ -1064,8 +1085,10 @@ public class Repository {
void fireIndexChanged() {
final IndexChangedEvent event = new IndexChangedEvent(this);
- for (final RepositoryListener l :
- listeners.toArray(new RepositoryListener[listeners.size()])) {
+ List<RepositoryListener> all = new ArrayList<RepositoryListener>(
+ listeners);
+ all.addAll(allListeners);
+ for (final RepositoryListener l : all) {
l.indexChanged(event);
}
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 5/9] Add a job to periodically scan for repository changes
2008-07-10 22:40 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 6/9] Change GitHistoryPage to listen on any repository Robin Rosenberg
2008-07-11 4:28 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Shawn O. Pearce
1 sibling, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/egit/ui/Activator.java | 75 ++++++++++++++++++++
.../src/org/spearce/jgit/lib/Repository.java | 10 +++
2 files changed, 85 insertions(+), 0 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
index 8d1b8cd..3e02c44 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
@@ -10,18 +10,27 @@ package org.spearce.egit.ui;
import java.net.Authenticator;
import java.net.ProxySelector;
+import java.util.HashSet;
+import java.util.Set;
import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.jobs.ISchedulingRule;
+import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jsch.core.IJSchService;
import org.eclipse.swt.graphics.Font;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.themes.ITheme;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
+import org.spearce.egit.core.project.RepositoryMapping;
+import org.spearce.jgit.lib.Repository;
import org.spearce.jgit.transport.SshSessionFactory;
/**
@@ -127,6 +136,7 @@ public class Activator extends AbstractUIPlugin {
}
private boolean traceVerbose;
+ private RCS rcs;
/**
* Constructor for the egit ui plugin singleton
@@ -140,6 +150,66 @@ public class Activator extends AbstractUIPlugin {
traceVerbose = isOptionSet("/trace/verbose");
setupSSH(context);
setupProxy(context);
+ setupRepoChangeScanner();
+ }
+
+ static class RCS extends Job {
+ RCS() {
+ super("Repository Change Scanner");
+ }
+
+ // FIXME, need to be more intelligent about this to avoid too much work
+ private static final long REPO_SCAN_INTERVAL = 10000L;
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ try {
+ // A repository can contain many projects, only scan once
+ // (a project could in theory be distributed among many
+ // repositories. We discard that as being ugly and stupid for
+ // the moment.
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ monitor.beginTask("Scanning Git repositories for changes", projects.length);
+ Set<Repository> scanned = new HashSet<Repository>();
+ for (IProject p : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null) {
+ Repository r = mapping.getRepository();
+ if (!scanned.contains(r)) {
+ if (monitor.isCanceled())
+ break;
+ trace("Scanning " + r + " for changes");
+ scanned.add(r);
+ ISchedulingRule rule = p.getWorkspace().getRuleFactory().modifyRule(p);
+ getJobManager().beginRule(rule, monitor);
+ try {
+ r.scanForRepoChanges();
+ } finally {
+ getJobManager().endRule(rule);
+ }
+ }
+ }
+ monitor.worked(1);
+ }
+ monitor.done();
+ trace("Rescheduling " + getName() + " job");
+ schedule(REPO_SCAN_INTERVAL);
+ } catch (Exception e) {
+ trace("Stopped rescheduling " + getName() + "job");
+ return new Status(
+ IStatus.ERROR,
+ getPluginId(),
+ 0,
+ "An error occurred while scanning for changes. Scanning aborted",
+ e);
+ }
+ return Status.OK_STATUS;
+ }
+ }
+
+ private void setupRepoChangeScanner() {
+ rcs = new RCS();
+ rcs.schedule(RCS.REPO_SCAN_INTERVAL);
}
private void setupSSH(final BundleContext context) {
@@ -165,6 +235,11 @@ public class Activator extends AbstractUIPlugin {
}
public void stop(final BundleContext context) throws Exception {
+ trace("Trying to cancel " + rcs.getName() + " job");
+ if (!rcs.cancel()) {
+ rcs.join();
+ }
+ trace("rcs.getName() " + rcs.getName() + " cancelled ok");
super.stop(context);
plugin = null;
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index dfa3045..9b65154 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -1092,4 +1092,14 @@ public class Repository {
l.indexChanged(event);
}
}
+
+ /**
+ * Force a scan for changed refs.
+ *
+ * @throws IOException
+ */
+ public void scanForRepoChanges() throws IOException {
+ getAllRefs(); // This will look for changes to refs
+ getIndex(); // This will detect changes in the index
+ }
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 6/9] Change GitHistoryPage to listen on any repository.
2008-07-10 22:40 ` [EGIT PATCH 5/9] Add a job to periodically scan for repository changes Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Robin Rosenberg
0 siblings, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
This makes listening simpler.
---
.../egit/ui/internal/history/GitHistoryPage.java | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
index 418f3b6..e3ff8d4 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
@@ -234,11 +234,16 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
attachContextMenu(commentViewer.getControl());
attachContextMenu(fileViewer.getControl());
layout();
+
+ Repository.addAnyRepositoryChangedListener(this);
}
private Runnable refschangedRunnable;
public void refsChanged(final RefsChangedEvent e) {
+ if (e.getRepository() != db)
+ return;
+
if (getControl().isDisposed())
return;
@@ -480,6 +485,7 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
}
public void dispose() {
+ Repository.removeAnyRepositoryChangedListener(this);
cancelRefreshJob();
if (popupMgr != null) {
for (final IContributionItem i : popupMgr.getItems()) {
@@ -539,9 +545,6 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
revObjectSelectionProvider.setActiveRepository(null);
cancelRefreshJob();
- if (db != null)
- db.removeRepositoryChangedListener(this);
-
if (graph == null)
return false;
@@ -570,8 +573,6 @@ public class GitHistoryPage extends HistoryPage implements RepositoryListener {
if (db == null)
return false;
- db.addRepositoryChangedListener(this);
-
final AnyObjectId headId;
try {
headId = db.resolve("HEAD");
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 7/9] Add a job to refresh projects when the index changes.
2008-07-10 22:40 ` [EGIT PATCH 6/9] Change GitHistoryPage to listen on any repository Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 8/9] Make git dectected changes depend on the automatic refresh setting Robin Rosenberg
2008-07-11 4:33 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Shawn O. Pearce
0 siblings, 2 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/egit/ui/Activator.java | 83 +++++++++++++++++++-
1 files changed, 79 insertions(+), 4 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
index 3e02c44..39d3bc9 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
@@ -11,16 +11,19 @@ package org.spearce.egit.ui;
import java.net.Authenticator;
import java.net.ProxySelector;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.net.proxy.IProxyService;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jsch.core.IJSchService;
@@ -30,7 +33,10 @@ import org.eclipse.ui.themes.ITheme;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.spearce.egit.core.project.RepositoryMapping;
+import org.spearce.jgit.lib.IndexChangedEvent;
+import org.spearce.jgit.lib.RefsChangedEvent;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.RepositoryListener;
import org.spearce.jgit.transport.SshSessionFactory;
/**
@@ -137,6 +143,7 @@ public class Activator extends AbstractUIPlugin {
private boolean traceVerbose;
private RCS rcs;
+ private RIRefresh refreshJob;
/**
* Constructor for the egit ui plugin singleton
@@ -151,6 +158,70 @@ public class Activator extends AbstractUIPlugin {
setupSSH(context);
setupProxy(context);
setupRepoChangeScanner();
+ setupRepoIndexRefresh();
+ }
+
+ private void setupRepoIndexRefresh() {
+ refreshJob = new RIRefresh();
+ Repository.addAnyRepositoryChangedListener(refreshJob);
+ }
+
+ static class RIRefresh extends Job implements RepositoryListener {
+
+ RIRefresh() {
+ super("Git index refresh Job");
+ }
+
+ private Set<IProject> projectsToScan = new LinkedHashSet<IProject>();
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ monitor.beginTask("Refreshing git managed projects", projects.length);
+
+ while (projectsToScan.size() > 0) {
+ IProject p;
+ synchronized (projectsToScan) {
+ if (projectsToScan.size() == 0) {
+ }
+ p = projectsToScan.iterator().next();
+ projectsToScan.remove(p);
+ }
+ ISchedulingRule rule = p.getWorkspace().getRuleFactory().refreshRule(p);
+ try {
+ getJobManager().beginRule(rule, monitor);
+ p.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1));
+ } catch (CoreException e) {
+ logError("Failed to refresh projects from index changes", e);
+ return new Status(IStatus.ERROR, getPluginId(), e.getMessage());
+ } finally {
+ getJobManager().endRule(rule);
+ }
+ }
+ monitor.done();
+ return Status.OK_STATUS;
+ }
+
+ public void indexChanged(IndexChangedEvent e) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ Set<IProject> toRefresh= new HashSet<IProject>();
+ for (IProject p : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null && mapping.getRepository() == e.getRepository()) {
+ toRefresh.add(p);
+ }
+ }
+ synchronized (projectsToScan) {
+ projectsToScan.addAll(toRefresh);
+ }
+ if (projectsToScan.size() > 0)
+ schedule();
+ }
+
+ public void refsChanged(RefsChangedEvent e) {
+ // Do not react here
+ }
+
}
static class RCS extends Job {
@@ -236,10 +307,14 @@ public class Activator extends AbstractUIPlugin {
public void stop(final BundleContext context) throws Exception {
trace("Trying to cancel " + rcs.getName() + " job");
- if (!rcs.cancel()) {
- rcs.join();
- }
- trace("rcs.getName() " + rcs.getName() + " cancelled ok");
+ rcs.cancel();
+ trace("Trying to cancel " + refreshJob.getName() + " job");
+ refreshJob.cancel();
+
+ rcs.join();
+ refreshJob.join();
+
+ trace("Jobs terminated");
super.stop(context);
plugin = null;
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 8/9] Make git dectected changes depend on the automatic refresh setting
2008-07-10 22:40 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 9/9] Attach the resource decorator to the repository change event mechanism Robin Rosenberg
2008-07-11 4:33 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Shawn O. Pearce
1 sibling, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
This is the same setting that scans the workspace regularly for
changes in resources. We scan more often can can trigger sooner because
we can scan fewer files.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/egit/ui/Activator.java | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
index 39d3bc9..d8928cb 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
@@ -203,6 +203,11 @@ public class Activator extends AbstractUIPlugin {
}
public void indexChanged(IndexChangedEvent e) {
+ // Check the workspace setting "refresh automatically" setting first
+ if (!ResourcesPlugin.getPlugin().getPluginPreferences().getBoolean(
+ ResourcesPlugin.PREF_AUTO_REFRESH))
+ return;
+
IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
Set<IProject> toRefresh= new HashSet<IProject>();
for (IProject p : projects) {
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [EGIT PATCH 9/9] Attach the resource decorator to the repository change event mechanism
2008-07-10 22:40 ` [EGIT PATCH 8/9] Make git dectected changes depend on the automatic refresh setting Robin Rosenberg
@ 2008-07-10 22:40 ` Robin Rosenberg
0 siblings, 0 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-10 22:40 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../internal/decorators/GitResourceDecorator.java | 29 +++++++++++++++++++-
1 files changed, 28 insertions(+), 1 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java
index 0308f6a..dcb87b7 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/decorators/GitResourceDecorator.java
@@ -10,6 +10,8 @@
package org.spearce.egit.ui.internal.decorators;
import java.io.IOException;
+import java.util.HashSet;
+import java.util.Set;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
@@ -38,7 +40,11 @@ import org.spearce.egit.ui.Activator;
import org.spearce.egit.ui.UIIcons;
import org.spearce.egit.ui.UIText;
import org.spearce.jgit.lib.GitIndex;
+import org.spearce.jgit.lib.IndexChangedEvent;
+import org.spearce.jgit.lib.RefsChangedEvent;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.RepositoryChangedEvent;
+import org.spearce.jgit.lib.RepositoryListener;
import org.spearce.jgit.lib.RepositoryState;
import org.spearce.jgit.lib.Tree;
import org.spearce.jgit.lib.TreeEntry;
@@ -61,7 +67,7 @@ public class GitResourceDecorator extends LabelProvider implements
private static final RCL myrcl = new RCL();
- static class RCL implements RepositoryChangeListener, Runnable {
+ static class RCL implements RepositoryChangeListener, RepositoryListener, Runnable {
private boolean requested;
public synchronized void run() {
@@ -70,6 +76,26 @@ public class GitResourceDecorator extends LabelProvider implements
GitResourceDecorator.class.getName());
}
+ public void refsChanged(RefsChangedEvent e) {
+ repositoryChanged(e);
+ }
+
+ public void indexChanged(IndexChangedEvent e) {
+ repositoryChanged(e);
+ }
+
+ private void repositoryChanged(RepositoryChangedEvent e) {
+ Set<RepositoryMapping> ms = new HashSet<RepositoryMapping>();
+ for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null && mapping.getRepository() == e.getRepository())
+ ms.add(mapping);
+ }
+ for (RepositoryMapping m : ms) {
+ repositoryChanged(m);
+ }
+ }
+
public void repositoryChanged(final RepositoryMapping which) {
try {
which.getContainer().accept(new IResourceVisitor() {
@@ -139,6 +165,7 @@ public class GitResourceDecorator extends LabelProvider implements
static ResCL myrescl = new ResCL();
static {
+ Repository.addAnyRepositoryChangedListener(myrcl);
GitProjectData.addRepositoryChangeListener(myrcl);
ResourcesPlugin.getWorkspace().addResourceChangeListener(myrescl,
IResourceChangeEvent.POST_CHANGE);
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [EGIT PATCH 1/9] Create a listener structure for changes to refs and index
2008-07-10 22:40 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 2/9] Cached modification times for symbolic refs too Robin Rosenberg
@ 2008-07-11 4:22 ` Shawn O. Pearce
2008-07-11 9:27 ` [PATCH] " Robin Rosenberg
1 sibling, 1 reply; 19+ messages in thread
From: Shawn O. Pearce @ 2008-07-11 4:22 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git, Marek Zawirski
Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> This version does not tell you which refs have changed, nor
> what changes have happened. There is not scanning for externally
> initiated changes either, though such changes can be found when
> a JGit client wants to read index or refs information.
> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
> index 9e3e020..4be33b8 100644
> --- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
> @@ -81,6 +81,10 @@ class RefDatabase {
>
> private long packedRefsLength;
>
> + long lastRefModification;
> +
> + long lastNotifiedRefModification;
> +
> RefDatabase(final Repository r) {
> db = r;
> gitDir = db.getDirectory();
> @@ -155,6 +161,12 @@ class RefDatabase {
> }
> if (!lck.commit())
> throw new ObjectWritingException("Unable to write " + name);
> + setModified();
> + db.fireRefsMaybeChanged();
> + }
> +
> + void setModified() {
> + lastRefModification = System.currentTimeMillis();
> }
We don't ever actually need the time here as a time, do we?
Wouldn't a simple counter work just as well, but ensure we don't
lose notifications that occur more frequently then the resolution
of currentTimeMillis()?
--
Shawn.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [EGIT PATCH 4/9] Add a method to listen to changes in any repository
2008-07-10 22:40 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 5/9] Add a job to periodically scan for repository changes Robin Rosenberg
@ 2008-07-11 4:28 ` Shawn O. Pearce
2008-07-11 9:48 ` [PATCH 4/4] " Robin Rosenberg
1 sibling, 1 reply; 19+ messages in thread
From: Shawn O. Pearce @ 2008-07-11 4:28 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git, Marek Zawirski
Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
> index 6f78652..dfa3045 100644
> --- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
> +++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
> @@ -95,6 +95,7 @@ public class Repository {
> private GitIndex index;
>
> private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
> + static private List<RepositoryListener> allListeners = new Vector<RepositoryListener>(); // thread safe
...
> void fireRefsMaybeChanged() {
> if (refs.lastRefModification != refs.lastNotifiedRefModification) {
> refs.lastNotifiedRefModification = refs.lastRefModification;
> final RefsChangedEvent event = new RefsChangedEvent(this);
> - for (final RepositoryListener l :
> - listeners.toArray(new RepositoryListener[listeners.size()])) {
> + List<RepositoryListener> all = new ArrayList<RepositoryListener>(
> + listeners);
> + all.addAll(allListeners);
> + for (final RepositoryListener l : all) {
> l.refsChanged(event);
I don't think this pattern is thread-safe like you think it is.
Adding (or removing) an allListener while you are trying
to copy the allListener collection for delivery can cause a
ConcurrentModificationException.
The preimage here is not even correct because toArray locks the
vector and will grow the input array if it was too small, but it
nulls out the later entries if the array was too large. Thus you
can NPE inside of the fire loop.
The only safe way to do this is to lock the collection while you copy
it into an array or list, then later iterate that to do the delivery.
Both of the fire implemenations in this patch have this issue. :-|
--
Shawn.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [EGIT PATCH 7/9] Add a job to refresh projects when the index changes.
2008-07-10 22:40 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 8/9] Make git dectected changes depend on the automatic refresh setting Robin Rosenberg
@ 2008-07-11 4:33 ` Shawn O. Pearce
2008-07-11 9:32 ` [PATCH 7/7] " Robin Rosenberg
1 sibling, 1 reply; 19+ messages in thread
From: Shawn O. Pearce @ 2008-07-11 4:33 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git, Marek Zawirski
Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> +
> + static class RIRefresh extends Job implements RepositoryListener {
...
> + while (projectsToScan.size() > 0) {
> + IProject p;
> + synchronized (projectsToScan) {
> + if (projectsToScan.size() == 0) {
> + }
> + p = projectsToScan.iterator().next();
This is going to throw some sort of no such element exception when
you call next when projectsToScan is empty. You are missing a
break inside of the if test that is meant to guard against this.
> + projectsToScan.remove(p);
> + }
You have gone to the trouble of allocating the Iterator to obtain
the next item, you should also just use it to do the deletion of
the next item. Its quicker to let the Iterator do the remove as
it already has the pointer to the proper element position.
--
Shawn.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [EGIT PATCH 0/9] Repository change listeners
2008-07-10 22:40 [EGIT PATCH 0/9] Repository change listeners Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Robin Rosenberg
@ 2008-07-11 5:26 ` Shawn O. Pearce
1 sibling, 0 replies; 19+ messages in thread
From: Shawn O. Pearce @ 2008-07-11 5:26 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: git, Marek Zawirski
Robin Rosenberg <robin.rosenberg@dewire.com> wrote:
> We want to make the UI react on changes to the repo, but the parts
> of the code that makes the changes doesn't know who wants to react
> on them. This adds a publish-subcribe mechanism, including detection
> of externally made changes, e.g. by C Git.
Aside from the few patches I commented on, I like the overall series
(not just this one, but the others you sent today as well). Its a
welcome improvement.
--
Shawn.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH] Create a listener structure for changes to refs and index
2008-07-11 4:22 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Shawn O. Pearce
@ 2008-07-11 9:27 ` Robin Rosenberg
0 siblings, 0 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-11 9:27 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
This version does not tell you which refs have changed, nor
what changes have happened. There is not scanning for externally
initiated changes either, though such changes can be found when
a JGit client wants to read index or refs information.
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../egit/ui/internal/history/GitHistoryPage.java | 31 +++++++++-
.../src/org/spearce/jgit/lib/GitIndex.java | 3 +
.../org/spearce/jgit/lib/IndexChangedEvent.java | 55 +++++++++++++++++
.../src/org/spearce/jgit/lib/RefDatabase.java | 19 ++++++
.../src/org/spearce/jgit/lib/RefsChangedEvent.java | 55 +++++++++++++++++
.../src/org/spearce/jgit/lib/Repository.java | 41 +++++++++++++
.../org/spearce/jgit/lib/RepositoryAdapter.java | 54 ++++++++++++++++
.../spearce/jgit/lib/RepositoryChangedEvent.java | 64 ++++++++++++++++++++
.../org/spearce/jgit/lib/RepositoryListener.java | 63 +++++++++++++++++++
9 files changed, 384 insertions(+), 1 deletions(-)
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
create mode 100644 org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
index 6b55185..7e2f726 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/internal/history/GitHistoryPage.java
@@ -61,7 +61,10 @@ import org.spearce.egit.ui.UIIcons;
import org.spearce.egit.ui.UIPreferences;
import org.spearce.egit.ui.UIText;
import org.spearce.jgit.lib.AnyObjectId;
+import org.spearce.jgit.lib.IndexChangedEvent;
+import org.spearce.jgit.lib.RefsChangedEvent;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.RepositoryListener;
import org.spearce.jgit.revplot.PlotCommit;
import org.spearce.jgit.revwalk.RevCommit;
import org.spearce.jgit.revwalk.RevFlag;
@@ -73,7 +76,7 @@ import org.spearce.jgit.treewalk.filter.PathFilterGroup;
import org.spearce.jgit.treewalk.filter.TreeFilter;
/** Graphical commit history viewer. */
-public class GitHistoryPage extends HistoryPage {
+public class GitHistoryPage extends HistoryPage implements RepositoryListener {
private static final String PREF_COMMENT_WRAP = UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_WRAP;
private static final String PREF_COMMENT_FILL = UIPreferences.RESOURCEHISTORY_SHOW_COMMENT_FILL;
@@ -230,6 +233,32 @@ public class GitHistoryPage extends HistoryPage {
layout();
}
+ private Runnable refschangedRunnable;
+
+ public void refsChanged(final RefsChangedEvent e) {
+ if (getControl().isDisposed())
+ return;
+
+ synchronized (this) {
+ if (refschangedRunnable == null) {
+ refschangedRunnable = new Runnable() {
+ public void run() {
+ if (!getControl().isDisposed()) {
+ Activator.trace("Executing async repository changed event");
+ refschangedRunnable = null;
+ inputSet();
+ }
+ }
+ };
+ getControl().getDisplay().asyncExec(refschangedRunnable);
+ }
+ }
+ }
+
+ public void indexChanged(final IndexChangedEvent e) {
+ // We do not use index information here now
+ }
+
private void finishContextMenu() {
popupMgr.add(new Separator());
popupMgr.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
index 5be404e..c7a4402 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/GitIndex.java
@@ -146,6 +146,7 @@ public class GitIndex {
public void rereadIfNecessary() throws IOException {
if (cacheFile.exists() && cacheFile.lastModified() != lastCacheTime) {
read();
+ db.fireIndexChanged();
}
}
@@ -269,6 +270,8 @@ public class GitIndex {
"Could not rename temporary index file to index");
changed = false;
statDirty = false;
+ lastCacheTime = cacheFile.lastModified();
+ db.fireIndexChanged();
} finally {
if (!lock.delete())
throw new IOException(
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
new file mode 100644
index 0000000..30a40d1
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/IndexChangedEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about a changed Git index to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class IndexChangedEvent extends RepositoryChangedEvent {
+ IndexChangedEvent(final Repository repository) {
+ super(repository);
+ }
+
+ @Override
+ public String toString() {
+ return "IndexChangedEvent[" + getRepository() + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
index 9e3e020..ebfa7f5 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefDatabase.java
@@ -81,6 +81,12 @@ class RefDatabase {
private long packedRefsLength;
+ long lastRefModification;
+
+ long lastNotifiedRefModification;
+
+ static int refModificationCounter;
+
RefDatabase(final Repository r) {
db = r;
gitDir = db.getDirectory();
@@ -132,6 +138,8 @@ class RefDatabase {
void stored(final String name, final ObjectId id, final long time) {
looseRefs.put(name, new CachedRef(Ref.Storage.LOOSE, name, id, time));
+ setModified();
+ db.fireRefsMaybeChanged();
}
/**
@@ -155,6 +163,12 @@ class RefDatabase {
}
if (!lck.commit())
throw new ObjectWritingException("Unable to write " + name);
+ setModified();
+ db.fireRefsMaybeChanged();
+ }
+
+ void setModified() {
+ lastRefModification = refModificationCounter++;
}
Ref readRef(final String partialName) throws IOException {
@@ -192,6 +206,7 @@ class RefDatabase {
readPackedRefs(avail);
readLooseRefs(avail, REFS_SLASH, refsDir);
readOneLooseRef(avail, Constants.HEAD, new File(gitDir, Constants.HEAD));
+ db.fireRefsMaybeChanged();
return avail;
}
@@ -321,6 +336,8 @@ class RefDatabase {
return r != null ? r : new Ref(Ref.Storage.LOOSE, target, null);
}
+ setModified();
+
final ObjectId id;
try {
id = ObjectId.fromString(line);
@@ -378,6 +395,7 @@ class RefDatabase {
packedRefsLastModified = currTime;
packedRefsLength = currLen;
packedRefs = newPackedRefs;
+ setModified();
} catch (FileNotFoundException noPackedRefs) {
// Ignore it and leave the new map empty.
//
@@ -414,4 +432,5 @@ class RefDatabase {
lastModified = mtime;
}
}
+
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
new file mode 100644
index 0000000..c8936c7
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RefsChangedEvent.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about a changed Git index to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class RefsChangedEvent extends RepositoryChangedEvent {
+ RefsChangedEvent(final Repository repository) {
+ super(repository);
+ }
+
+ @Override
+ public String toString() {
+ return "RefsChangedEvent[" + getRepository() + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 04d9b13..6f78652 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -49,7 +49,9 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedList;
+import java.util.List;
import java.util.Map;
+import java.util.Vector;
import org.spearce.jgit.errors.IncorrectObjectTypeException;
import org.spearce.jgit.errors.RevisionSyntaxException;
@@ -92,6 +94,8 @@ public class Repository {
private GitIndex index;
+ private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
+
/**
* Construct a representation of a Git repository.
*
@@ -1028,4 +1032,41 @@ public class Repository {
public File getWorkDir() {
return getDirectory().getParentFile();
}
+
+ /**
+ * Register a {@link RepositoryListener} which will be notified
+ * when ref changes are detected.
+ *
+ * @param l
+ */
+ public void addRepositoryChangedListener(final RepositoryListener l) {
+ listeners.add(l);
+ }
+
+ /**
+ * Remove a registered {@link RepositoryListener}
+ * @param l
+ */
+ public void removeRepositoryChangedListener(final RepositoryListener l) {
+ listeners.remove(l);
+ }
+
+ void fireRefsMaybeChanged() {
+ if (refs.lastRefModification != refs.lastNotifiedRefModification) {
+ refs.lastNotifiedRefModification = refs.lastRefModification;
+ final RefsChangedEvent event = new RefsChangedEvent(this);
+ for (final RepositoryListener l :
+ listeners.toArray(new RepositoryListener[listeners.size()])) {
+ l.refsChanged(event);
+ }
+ }
+ }
+
+ void fireIndexChanged() {
+ final IndexChangedEvent event = new IndexChangedEvent(this);
+ for (final RepositoryListener l :
+ listeners.toArray(new RepositoryListener[listeners.size()])) {
+ l.indexChanged(event);
+ }
+ }
}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
new file mode 100644
index 0000000..d1ff07d
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryAdapter.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * A default {@link RepositoryListener} that does nothing except invoke an
+ * optional general method for any repository change.
+ */
+public class RepositoryAdapter implements RepositoryListener {
+
+ public void indexChanged(final IndexChangedEvent e) {
+ // Empty
+ }
+
+ public void refsChanged(final RefsChangedEvent e) {
+ // Empty
+ }
+
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
new file mode 100644
index 0000000..b58df87
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryChangedEvent.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * This class passes information about changed refs to a
+ * {@link RepositoryListener}
+ *
+ * Currently only a reference to the repository is passed.
+ */
+public class RepositoryChangedEvent {
+ private final Repository repository;
+
+ RepositoryChangedEvent(final Repository repository) {
+ this.repository = repository;
+ }
+
+ /**
+ * @return the repository that was changed
+ */
+ public Repository getRepository() {
+ return repository;
+ }
+
+ @Override
+ public String toString() {
+ return "RepositoryChangedEvent[" + repository + "]";
+ }
+}
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
new file mode 100644
index 0000000..ceb14ce
--- /dev/null
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/RepositoryListener.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
+ *
+ * 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 Git Development Community 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.spearce.jgit.lib;
+
+/**
+ * A RepositoryListener gets notification about changes in refs or repository.
+ * <p>
+ * It currently does <em>not</em> get notification about which items are
+ * changed.
+ */
+public interface RepositoryListener {
+ /**
+ * Invoked when a ref changes
+ *
+ * @param e
+ * information about the changes.
+ */
+ void refsChanged(RefsChangedEvent e);
+
+ /**
+ * Invoked when the index changes
+ *
+ * @param e
+ * information about the changes.
+ */
+ void indexChanged(IndexChangedEvent e);
+
+}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 7/7] Add a job to refresh projects when the index changes.
2008-07-11 4:33 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Shawn O. Pearce
@ 2008-07-11 9:32 ` Robin Rosenberg
0 siblings, 0 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-11 9:32 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/egit/ui/Activator.java | 85 +++++++++++++++++++-
1 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
index 3e02c44..89e6579 100644
--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
+++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/Activator.java
@@ -11,16 +11,20 @@ package org.spearce.egit.ui;
import java.net.Authenticator;
import java.net.ProxySelector;
import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashSet;
import java.util.Set;
import org.eclipse.core.net.proxy.IProxyService;
import org.eclipse.core.resources.IProject;
+import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
+import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jsch.core.IJSchService;
@@ -30,7 +34,10 @@ import org.eclipse.ui.themes.ITheme;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.spearce.egit.core.project.RepositoryMapping;
+import org.spearce.jgit.lib.IndexChangedEvent;
+import org.spearce.jgit.lib.RefsChangedEvent;
import org.spearce.jgit.lib.Repository;
+import org.spearce.jgit.lib.RepositoryListener;
import org.spearce.jgit.transport.SshSessionFactory;
/**
@@ -137,6 +144,7 @@ public class Activator extends AbstractUIPlugin {
private boolean traceVerbose;
private RCS rcs;
+ private RIRefresh refreshJob;
/**
* Constructor for the egit ui plugin singleton
@@ -151,6 +159,71 @@ public class Activator extends AbstractUIPlugin {
setupSSH(context);
setupProxy(context);
setupRepoChangeScanner();
+ setupRepoIndexRefresh();
+ }
+
+ private void setupRepoIndexRefresh() {
+ refreshJob = new RIRefresh();
+ Repository.addAnyRepositoryChangedListener(refreshJob);
+ }
+
+ static class RIRefresh extends Job implements RepositoryListener {
+
+ RIRefresh() {
+ super("Git index refresh Job");
+ }
+
+ private Set<IProject> projectsToScan = new LinkedHashSet<IProject>();
+
+ @Override
+ protected IStatus run(IProgressMonitor monitor) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ monitor.beginTask("Refreshing git managed projects", projects.length);
+
+ while (projectsToScan.size() > 0) {
+ IProject p;
+ synchronized (projectsToScan) {
+ if (projectsToScan.size() == 0)
+ break;
+ Iterator<IProject> i = projectsToScan.iterator();
+ p = i.next();
+ i.remove();
+ }
+ ISchedulingRule rule = p.getWorkspace().getRuleFactory().refreshRule(p);
+ try {
+ getJobManager().beginRule(rule, monitor);
+ p.refreshLocal(IResource.DEPTH_INFINITE, new SubProgressMonitor(monitor, 1));
+ } catch (CoreException e) {
+ logError("Failed to refresh projects from index changes", e);
+ return new Status(IStatus.ERROR, getPluginId(), e.getMessage());
+ } finally {
+ getJobManager().endRule(rule);
+ }
+ }
+ monitor.done();
+ return Status.OK_STATUS;
+ }
+
+ public void indexChanged(IndexChangedEvent e) {
+ IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
+ Set<IProject> toRefresh= new HashSet<IProject>();
+ for (IProject p : projects) {
+ RepositoryMapping mapping = RepositoryMapping.getMapping(p);
+ if (mapping != null && mapping.getRepository() == e.getRepository()) {
+ toRefresh.add(p);
+ }
+ }
+ synchronized (projectsToScan) {
+ projectsToScan.addAll(toRefresh);
+ }
+ if (projectsToScan.size() > 0)
+ schedule();
+ }
+
+ public void refsChanged(RefsChangedEvent e) {
+ // Do not react here
+ }
+
}
static class RCS extends Job {
@@ -236,10 +309,14 @@ public class Activator extends AbstractUIPlugin {
public void stop(final BundleContext context) throws Exception {
trace("Trying to cancel " + rcs.getName() + " job");
- if (!rcs.cancel()) {
- rcs.join();
- }
- trace("rcs.getName() " + rcs.getName() + " cancelled ok");
+ rcs.cancel();
+ trace("Trying to cancel " + refreshJob.getName() + " job");
+ refreshJob.cancel();
+
+ rcs.join();
+ refreshJob.join();
+
+ trace("Jobs terminated");
super.stop(context);
plugin = null;
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH 4/4] Add a method to listen to changes in any repository
2008-07-11 4:28 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Shawn O. Pearce
@ 2008-07-11 9:48 ` Robin Rosenberg
2008-07-11 12:24 ` jgit (was: [PATCH 4/4] Add a method...) Andreas Ericsson
0 siblings, 1 reply; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-11 9:48 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: git, Marek Zawirski, Robin Rosenberg
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
.../src/org/spearce/jgit/lib/Repository.java | 39 ++++++++++++++++++--
1 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 52f6750..af860b3 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -95,6 +95,7 @@ public class Repository {
private GitIndex index;
private List<RepositoryListener> listeners = new Vector<RepositoryListener>(); // thread safe
+ static private List<RepositoryListener> allListeners = new Vector<RepositoryListener>(); // thread safe
/**
* Construct a representation of a Git repository.
@@ -1051,12 +1052,36 @@ public class Repository {
listeners.remove(l);
}
+ /**
+ * Register a global {@link RepositoryListener} which will be notified
+ * when a ref changes in any repository are detected.
+ *
+ * @param l
+ */
+ public static void addAnyRepositoryChangedListener(final RepositoryListener l) {
+ allListeners.add(l);
+ }
+
+ /**
+ * Remove a globally registered {@link RepositoryListener}
+ * @param l
+ */
+ public static void removeAnyRepositoryChangedListener(final RepositoryListener l) {
+ allListeners.remove(l);
+ }
+
void fireRefsMaybeChanged() {
if (refs.lastRefModification != refs.lastNotifiedRefModification) {
refs.lastNotifiedRefModification = refs.lastRefModification;
final RefsChangedEvent event = new RefsChangedEvent(this);
- for (final RepositoryListener l :
- listeners.toArray(new RepositoryListener[0])) {
+ List<RepositoryListener> all;
+ synchronized (listeners) {
+ all = new ArrayList<RepositoryListener>(listeners);
+ }
+ synchronized (allListeners) {
+ all.addAll(allListeners);
+ }
+ for (final RepositoryListener l : all) {
l.refsChanged(event);
}
}
@@ -1064,8 +1089,14 @@ public class Repository {
void fireIndexChanged() {
final IndexChangedEvent event = new IndexChangedEvent(this);
- for (final RepositoryListener l :
- listeners.toArray(new RepositoryListener[0])) {
+ List<RepositoryListener> all;
+ synchronized (listeners) {
+ all = new ArrayList<RepositoryListener>(listeners);
+ }
+ synchronized (allListeners) {
+ all.addAll(allListeners);
+ }
+ for (final RepositoryListener l : all) {
l.indexChanged(event);
}
}
--
1.5.6.2.220.g44701
^ permalink raw reply related [flat|nested] 19+ messages in thread
* jgit (was: [PATCH 4/4] Add a method...)
2008-07-11 9:48 ` [PATCH 4/4] " Robin Rosenberg
@ 2008-07-11 12:24 ` Andreas Ericsson
2008-07-11 12:24 ` Robin Rosenberg
0 siblings, 1 reply; 19+ messages in thread
From: Andreas Ericsson @ 2008-07-11 12:24 UTC (permalink / raw)
To: Robin Rosenberg; +Cc: Shawn O. Pearce, git, Marek Zawirski
Sorry for butting in, but I'd appreciate if you kept adding 'jgit'
to the subject so I can keep filtering these patches out. The volume
on git@vger is high enough without having to follow off-shoots that
are of no particular concern to me (although I certainly applaud the
effort).
Thanks
Robin Rosenberg wrote:
[ a patch for jgit ]
--
Andreas Ericsson andreas.ericsson@op5.se
OP5 AB www.op5.se
Tel: +46 8-230225 Fax: +46 8-230231
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: jgit (was: [PATCH 4/4] Add a method...)
2008-07-11 12:24 ` jgit (was: [PATCH 4/4] Add a method...) Andreas Ericsson
@ 2008-07-11 12:24 ` Robin Rosenberg
0 siblings, 0 replies; 19+ messages in thread
From: Robin Rosenberg @ 2008-07-11 12:24 UTC (permalink / raw)
To: Andreas Ericsson; +Cc: Shawn O. Pearce, git, Marek Zawirski
fredagen den 11 juli 2008 14.24.03 skrev Andreas Ericsson:
> Sorry for butting in, but I'd appreciate if you kept adding 'jgit'
> to the subject so I can keep filtering these patches out. The volume
> on git@vger is high enough without having to follow off-shoots that
> are of no particular concern to me (although I certainly applaud the
> effort).
It was an accident. Honestly :)
-- robin
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2008-07-11 12:30 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-07-10 22:40 [EGIT PATCH 0/9] Repository change listeners Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 2/9] Cached modification times for symbolic refs too Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 3/9] Connect the history page to the refs update subscription mechanism Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 5/9] Add a job to periodically scan for repository changes Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 6/9] Change GitHistoryPage to listen on any repository Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 8/9] Make git dectected changes depend on the automatic refresh setting Robin Rosenberg
2008-07-10 22:40 ` [EGIT PATCH 9/9] Attach the resource decorator to the repository change event mechanism Robin Rosenberg
2008-07-11 4:33 ` [EGIT PATCH 7/9] Add a job to refresh projects when the index changes Shawn O. Pearce
2008-07-11 9:32 ` [PATCH 7/7] " Robin Rosenberg
2008-07-11 4:28 ` [EGIT PATCH 4/9] Add a method to listen to changes in any repository Shawn O. Pearce
2008-07-11 9:48 ` [PATCH 4/4] " Robin Rosenberg
2008-07-11 12:24 ` jgit (was: [PATCH 4/4] Add a method...) Andreas Ericsson
2008-07-11 12:24 ` Robin Rosenberg
2008-07-11 4:22 ` [EGIT PATCH 1/9] Create a listener structure for changes to refs and index Shawn O. Pearce
2008-07-11 9:27 ` [PATCH] " Robin Rosenberg
2008-07-11 5:26 ` [EGIT PATCH 0/9] Repository change listeners Shawn O. Pearce
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).