diff --git a/Ghidra/Configurations/Public_Release/build.gradle b/Ghidra/Configurations/Public_Release/build.gradle
index 632a51d42a..f80f99df37 100644
--- a/Ghidra/Configurations/Public_Release/build.gradle
+++ b/Ghidra/Configurations/Public_Release/build.gradle
@@ -20,3 +20,9 @@ apply from: "$rootProject.projectDir/gradle/javaTestProject.gradle"
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply plugin: 'eclipse'
eclipse.project.name = 'Z Public Release'
+
+rootProject.assembleDistribution {
+ from ("${this.projectDir}/src/main/resources/UserAgreement.html") {
+ into "docs"
+ }
+}
diff --git a/Ghidra/Configurations/Public_Release/certification.manifest b/Ghidra/Configurations/Public_Release/certification.manifest
index 9ad85924a3..f2b4a77268 100644
--- a/Ghidra/Configurations/Public_Release/certification.manifest
+++ b/Ghidra/Configurations/Public_Release/certification.manifest
@@ -3,7 +3,6 @@ Module.manifest||GHIDRA||||END|
README.md||GHIDRA||||END|
data/PDB_SYMBOL_SERVER_URLS.pdburl||GHIDRA||||END|
src/global/docs/ChangeHistory.html||GHIDRA||||END|
-src/global/docs/UserAgreement.html||GHIDRA||||END|
src/global/docs/WhatsNew.md||GHIDRA||||END|
src/main/resources/UserAgreement.html||GHIDRA||||END|
src/main/resources/defaultTools/CodeBrowser.tool||GHIDRA||||END|
diff --git a/Ghidra/Configurations/Public_Release/src/global/docs/UserAgreement.html b/Ghidra/Configurations/Public_Release/src/global/docs/UserAgreement.html
deleted file mode 100644
index 7fe98a6e27..0000000000
--- a/Ghidra/Configurations/Public_Release/src/global/docs/UserAgreement.html
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- Ghidra User Agreement
-
-
-
-
-Licensed under the Apache License, Version 2.0 (the "License"); Unless required by applicable law or
-agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
-specific language governing permissions and limitations under the License.
-
-
-As a software reverse engineering (SRE) framework, Ghidra is designed solely to facilitate
-lawful SRE activities. You should always ensure that any SRE activities in which you engage are
-permissible as computer software may be protected under governing law (e.g., copyright) or under an
-applicable licensing agreement. In making Ghidra available for public use, the National Security
-Agency does not condone or encourage any improper usage of Ghidra. Consistent with the Apache 2.0
-license under which Ghidra has been made available, you are solely responsible for determining the
-appropriateness of using or redistributing Ghidra.
-
-
-
diff --git a/Ghidra/Configurations/Public_Release/src/main/resources/UserAgreement.html b/Ghidra/Configurations/Public_Release/src/main/resources/UserAgreement.html
index 1285f35cee..7fe98a6e27 100644
--- a/Ghidra/Configurations/Public_Release/src/main/resources/UserAgreement.html
+++ b/Ghidra/Configurations/Public_Release/src/main/resources/UserAgreement.html
@@ -1,4 +1,7 @@
+
+ Ghidra User Agreement
+
diff --git a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java
index 4ae8aca1ab..adc425c779 100644
--- a/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java
+++ b/Ghidra/Features/Base/src/main/java/ghidra/app/plugin/core/misc/MyProgramChangesDisplayPlugin.java
@@ -102,9 +102,16 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
private int serverVersion = -1;
private int localVersion = -1;
- private boolean programChangedLocally;
- private boolean programChangedRemotely;
- private boolean programSaved;
+ // currentProgram object changed; affects currentMyChangeMarks
+ private boolean currentProgramChanged;
+
+ // domain file updated on server; affects currentOtherChangeMarks
+ private boolean domainFileChangedRemotely;
+
+ // domain file updated locally; affects currentChangesSinceCheckoutMarks
+ private boolean domainFileChangedLocally;
+
+ // flag to force update of currentConflictChangeMarks
private boolean updateConflicts;
public MyProgramChangesDisplayPlugin(PluginTool tool) {
@@ -181,9 +188,9 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
serverVersion = -1;
localVersion = -1;
- programChangedLocally = false;
- programChangedRemotely = false;
- programSaved = false;
+ currentProgramChanged = false;
+ domainFileChangedRemotely = false;
+ domainFileChangedLocally = false;
program.removeTransactionListener(transactionListener);
program.removeListener(this);
disposeMarkerSets(program);
@@ -191,9 +198,9 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
private void intializeChangeMarkers() {
// set all the triggers for updating markers when initializing
- programChangedLocally = true;
- programChangedRemotely = true;
- programSaved = true;
+ currentProgramChanged = true;
+ domainFileChangedRemotely = true;
+ domainFileChangedLocally = true;
updateConflicts = true;
updateChangeMarkers();
}
@@ -273,24 +280,25 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
ProgramChangeSet changeSet = currentProgram.getChanges();
- if (programChangedLocally) {
+ if (currentProgramChanged) {
currentMyChangeMarks
.setAddressSetCollection(changeSet.getAddressSetCollectionSinceLastSave());
}
if (isTrackingServerChanges()) {
- if (programSaved || programChangedRemotely) {
+ if (domainFileChangedLocally) {
currentChangesSinceCheckoutMarks
.setAddressSetCollection(changeSet.getAddressSetCollectionSinceCheckout());
}
- if (programChangedRemotely) {
+ if (domainFileChangedRemotely) {
currentOtherChangeMarks
.setAddressSetCollection(new SingleAddressSetCollection(otherChangeSet));
}
- // only update conflict markers when server changeSet changes or we end a transaction
- if (programChangedRemotely || updateConflicts) {
+ // Update conflict markers when forced by server version change,
+ // local version change (merge may have occured) or a transaction has ended
+ if (updateConflicts) {
AddressSet intersect = changeSet.getAddressSetCollectionSinceCheckout()
.getCombinedAddressSet()
.intersect(otherChangeSet);
@@ -299,9 +307,9 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
}
}
- programChangedLocally = false;
- programChangedRemotely = false;
- programSaved = false;
+ currentProgramChanged = false;
+ domainFileChangedRemotely = false;
+ domainFileChangedLocally = false;
updateConflicts = false;
}
@@ -310,30 +318,43 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
* checkout and launch update thread if necessary.
*/
private void updateForDomainFileChanged() {
+
DomainFile df = currentProgram.getDomainFile();
+ if (!df.isCheckedOut()) {
+ // Only currentMyChangeMarks are maintained using domain object change listener
+ // when file is not checked-out
+ return;
+ }
int latestServerVersion = df.getLatestVersion();
int latestLocalVersion = df.getVersion();
- // if the server version changes, schedule thread to get server changeSet
- // which will trigger an marker update for both the other and conflict marker sets.
- if (df.isCheckedOut() && serverVersion != latestServerVersion) {
- serverVersion = latestServerVersion;
- localVersion = latestLocalVersion;
- if (serverVersion == localVersion) {
- otherChangeSet = new AddressSet();
- programChangedRemotely = true;
- updateManager.update();
- }
- else {
- scheduleUpdatesFromServer(currentProgram);
- }
+
+ boolean localVersionChanged = localVersion != latestLocalVersion;
+ boolean serverVersionChanged = serverVersion != latestServerVersion;
+ if (!localVersionChanged && !serverVersionChanged) {
+ return; // No update to change bars
}
- // else just the local version changed, update conflict sets.
- else if (latestLocalVersion != localVersion) {
- localVersion = latestLocalVersion;
- updateConflicts = true;
- updateManager.update();
+
+ localVersion = latestLocalVersion;
+ serverVersion = latestServerVersion;
+
+ domainFileChangedLocally |= localVersionChanged;
+ domainFileChangedRemotely |= serverVersionChanged;
+ updateConflicts = true;
+
+ if (localVersion == serverVersion) {
+ // When server and local versions match otherChangeSet is empty
+ otherChangeSet = new AddressSet();
+ domainFileChangedRemotely = true;
}
+ else if (serverVersionChanged) {
+ // Use UpdateChangeSetJob to compute the otherChangeSet
+ // GUI update deferred to UpdateChangeSetJob
+ scheduleUpdatesFromServer(currentProgram);
+ return;
+ }
+
+ updateManager.update();
}
private void scheduleUpdatesFromServer(Program p) {
@@ -350,9 +371,9 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
@Override
public void domainObjectChanged(DomainObjectChangedEvent ev) {
- programChangedLocally = true;
+ currentProgramChanged = true;
if (ev.contains(DomainObjectEvent.SAVED)) {
- programSaved = true;
+ domainFileChangedLocally = true;
}
updateManager.update();
@@ -428,6 +449,10 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
@Override
public void run(TaskMonitor monitor) throws CancelledException {
+ if (localVersion == serverVersion) {
+ return; // skip update if versions now match
+ }
+
monitor.checkCancelled(); // plugin was shut down while we were scheduled
ProgramChangeSet changes = null;
@@ -456,7 +481,8 @@ public class MyProgramChangesDisplayPlugin extends ProgramPlugin implements Doma
}
otherChangeSet = remoteChanges;
- programChangedRemotely = true;
+ domainFileChangedRemotely = true;
+ updateConflicts = true;
updateManager.update();
}
}
diff --git a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java
index 7ab51d95e3..17b258fb66 100644
--- a/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java
+++ b/Ghidra/Framework/Project/src/main/java/ghidra/framework/data/GhidraFileData.java
@@ -4,9 +4,9 @@
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -89,6 +89,7 @@ public class GhidraFileData {
private Icon disabledIcon;
private AtomicBoolean busy = new AtomicBoolean();
+ private boolean mergeInProgress = false;
// TODO: Many of the old methods assumed that the state was up-to-date due to
// refreshing ... we are relying on non-refreshed data to be dropped from cache map and no
@@ -196,6 +197,9 @@ public class GhidraFileData {
}
private void statusChanged(boolean fileIDset) throws IOException {
+ if (mergeInProgress) {
+ return;
+ }
icon = null;
disabledIcon = null;
fileIDset |= refresh();
@@ -1099,6 +1103,7 @@ public class GhidraFileData {
}
DomainObjectAdapterDB inUseDomainObj = null;
+ mergeInProgress = true;
projectData.mergeStarted();
try {
inUseDomainObj = getAndLockInUseDomainObjectForMergeUpdate("checkin");
@@ -1195,6 +1200,7 @@ public class GhidraFileData {
finally {
unlockDomainObject(inUseDomainObj);
busy.set(false);
+ mergeInProgress = false;
projectData.mergeEnded();
parent.deleteLocalFolderIfEmpty();
parent.fileChanged(name);
@@ -1430,6 +1436,7 @@ public class GhidraFileData {
}
DomainObjectAdapterDB inUseDomainObj = null;
+ mergeInProgress = true;
projectData.mergeStarted();
try {
ContentHandler> contentHandler = getContentHandler();
@@ -1556,6 +1563,7 @@ public class GhidraFileData {
finally {
unlockDomainObject(inUseDomainObj);
busy.set(false);
+ mergeInProgress = false;
projectData.mergeEnded();
parent.deleteLocalFolderIfEmpty();
parent.fileChanged(name);
@@ -1914,6 +1922,7 @@ public class GhidraFileData {
FolderItem tmpItem = null;
DomainObjectAdapterDB inUseDomainObj = null;
+ mergeInProgress = true;
projectData.mergeStarted();
try {
inUseDomainObj = getAndLockInUseDomainObjectForMergeUpdate("merge");
@@ -2011,6 +2020,7 @@ public class GhidraFileData {
finally {
unlockDomainObject(inUseDomainObj);
busy.set(false);
+ mergeInProgress = false;
try {
if (tmpItem != null) {
try {