summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--desktop-widgets/maintab.cpp4
-rw-r--r--desktop-widgets/simplewidgets.cpp8
-rw-r--r--profile-widget/profilewidget2.cpp4
-rw-r--r--qt-mobile/qmlmanager.cpp1
-rw-r--r--subsurface-core/dive.c15
-rw-r--r--subsurface-core/dive.h13
-rw-r--r--subsurface-core/load-git.c11
-rw-r--r--subsurface-core/save-git.c37
8 files changed, 77 insertions, 16 deletions
diff --git a/desktop-widgets/maintab.cpp b/desktop-widgets/maintab.cpp
index 3c9518247..eddf90b98 100644
--- a/desktop-widgets/maintab.cpp
+++ b/desktop-widgets/maintab.cpp
@@ -1049,8 +1049,10 @@ void MainTab::acceptChanges()
// each dive that was selected might have had the temperatures in its active divecomputer changed
// so re-populate the temperatures - easiest way to do this is by calling fixup_dive
for_each_dive (i, d) {
- if (d->selected)
+ if (d->selected) {
fixup_dive(d);
+ invalidate_dive_cache(d);
+ }
}
}
if (editMode != TRIP && current_dive->divetrip) {
diff --git a/desktop-widgets/simplewidgets.cpp b/desktop-widgets/simplewidgets.cpp
index 6d46a49c7..6c9ec3f96 100644
--- a/desktop-widgets/simplewidgets.cpp
+++ b/desktop-widgets/simplewidgets.cpp
@@ -153,8 +153,10 @@ void RenumberDialog::buttonClicked(QAbstractButton *button)
int newNr = ui.spinBox->value();
struct dive *dive = NULL;
for_each_dive (i, dive) {
- if (!selectedOnly || dive->selected)
+ if (!selectedOnly || dive->selected) {
+ invalidate_dive_cache(dive);
renumberedDives.insert(dive->id, QPair<int,int>(dive->number, newNr++));
+ }
}
UndoRenumberDives *undoCommand = new UndoRenumberDives(renumberedDives);
MainWindow::instance()->undoStack->push(undoCommand);
@@ -189,8 +191,10 @@ void SetpointDialog::setpointData(struct divecomputer *divecomputer, int second)
void SetpointDialog::buttonClicked(QAbstractButton *button)
{
- if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole && dc)
+ if (ui.buttonBox->buttonRole(button) == QDialogButtonBox::AcceptRole && dc) {
add_event(dc, time, SAMPLE_EVENT_PO2, 0, (int)(1000.0 * ui.spinbox->value()), "SP change");
+ invalidate_dive_cache(current_dive);
+ }
mark_divelist_changed(true);
MainWindow::instance()->graphics()->replot();
}
diff --git a/profile-widget/profilewidget2.cpp b/profile-widget/profilewidget2.cpp
index e4b03ebcb..35a9594a3 100644
--- a/profile-widget/profilewidget2.cpp
+++ b/profile-widget/profilewidget2.cpp
@@ -1515,6 +1515,7 @@ void ProfileWidget2::removeEvent()
tr("%1 @ %2:%3").arg(event->name).arg(event->time.seconds / 60).arg(event->time.seconds % 60, 2, 10, QChar('0'))),
QMessageBox::Ok | QMessageBox::Cancel) == QMessageBox::Ok) {
remove_event(event);
+ invalidate_dive_cache(current_dive);
mark_divelist_changed(true);
replot();
}
@@ -1525,6 +1526,7 @@ void ProfileWidget2::addBookmark()
QAction *action = qobject_cast<QAction *>(sender());
QPointF scenePos = mapToScene(mapFromGlobal(action->data().toPoint()));
add_event(current_dc, timeAxis->valueAt(scenePos), SAMPLE_EVENT_BOOKMARK, 0, 0, "bookmark");
+ invalidate_dive_cache(current_dive);
mark_divelist_changed(true);
replot();
}
@@ -1575,6 +1577,7 @@ void ProfileWidget2::changeGas()
add_gas_switch_event(&displayed_dive, get_dive_dc(&displayed_dive, dc_number), seconds, tank);
// this means we potentially have a new tank that is being used and needs to be shown
fixup_dive(&displayed_dive);
+ invalidate_dive_cache(current_dive);
// FIXME - this no longer gets written to the dive list - so we need to enableEdition() here
@@ -1647,6 +1650,7 @@ void ProfileWidget2::editName()
// and will be freed as part of changing the name!
update_event_name(current_dive, event, newName.toUtf8().data());
update_event_name(&displayed_dive, event, newName.toUtf8().data());
+ invalidate_dive_cache(current_dive);
mark_divelist_changed(true);
replot();
}
diff --git a/qt-mobile/qmlmanager.cpp b/qt-mobile/qmlmanager.cpp
index 048e787cf..c6e6c5025 100644
--- a/qt-mobile/qmlmanager.cpp
+++ b/qt-mobile/qmlmanager.cpp
@@ -447,6 +447,7 @@ void QMLManager::commitChanges(QString diveId, QString date, QString location, Q
bool diveChanged = false;
bool needResort = false;
+ invalidate_dive_cache(d);
if (date != get_dive_date_string(d->when)) {
diveChanged = needResort = true;
QDateTime newDate;
diff --git a/subsurface-core/dive.c b/subsurface-core/dive.c
index 12154704f..ce730da28 100644
--- a/subsurface-core/dive.c
+++ b/subsurface-core/dive.c
@@ -156,6 +156,7 @@ void update_event_name(struct dive *d, struct event *event, char *name)
*removep = (*removep)->next;
add_event(dc, event->time.seconds, event->type, event->flags, event->value, name);
free(remove);
+ invalidate_dive_cache(d);
}
void add_extra_data(struct divecomputer *dc, const char *key, const char *value)
@@ -464,6 +465,7 @@ void copy_dive(struct dive *s, struct dive *d)
* relevant components that are referenced through pointers,
* so all the strings and the structured lists */
*d = *s;
+ invalidate_dive_cache(d);
d->buddy = copy_string(s->buddy);
d->divemaster = copy_string(s->divemaster);
d->notes = copy_string(s->notes);
@@ -474,11 +476,10 @@ void copy_dive(struct dive *s, struct dive *d)
d->weightsystem[i].description = copy_string(s->weightsystem[i].description);
STRUCTURED_LIST_COPY(struct picture, s->picture_list, d->picture_list, copy_pl);
STRUCTURED_LIST_COPY(struct tag_entry, s->tag_list, d->tag_list, copy_tl);
+
+ // Copy the first dc explicitly, then the list of subsequent dc's
+ copy_dc(&s->dc, &d->dc);
STRUCTURED_LIST_COPY(struct divecomputer, s->dc.next, d->dc.next, copy_dc);
- /* this only copied dive computers 2 and up. The first dive computer is part
- * of the struct dive, so let's make copies of its samples and events */
- copy_samples(&s->dc, &d->dc);
- copy_events(&s->dc, &d->dc);
}
/* make a clone of the source dive and clean out the source dive;
@@ -3247,6 +3248,7 @@ void shift_times(const timestamp_t amount)
if (!dive->selected)
continue;
dive->when += amount;
+ invalidate_dive_cache(dive);
}
}
@@ -3410,6 +3412,7 @@ void dive_create_picture(struct dive *dive, char *filename, int shift_time, bool
dive_add_picture(dive, picture);
dive_set_geodata_from_picture(dive, picture);
+ invalidate_dive_cache(dive);
}
void dive_add_picture(struct dive *dive, struct picture *newpic)
@@ -3441,6 +3444,7 @@ void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture)
ds->longitude = picture->longitude;
} else {
dive->dive_site_uuid = create_dive_site_with_gps("", picture->latitude, picture->longitude, dive->when);
+ invalidate_dive_cache(dive);
}
}
}
@@ -3475,6 +3479,7 @@ void dive_remove_picture(char *filename)
struct picture *temp = (*picture)->next;
picture_free(*picture);
*picture = temp;
+ invalidate_dive_cache(current_dive);
}
}
@@ -3498,6 +3503,7 @@ void make_first_dc()
current_dive->dc = *cur_dc;
current_dive->dc.next = newdc;
free(cur_dc);
+ invalidate_dive_cache(current_dive);
}
/* always acts on the current dive */
@@ -3537,6 +3543,7 @@ void delete_current_divecomputer(void)
}
if (dc_number == count_divecomputers())
dc_number--;
+ invalidate_dive_cache(current_dive);
}
/* helper function to make it easier to work with our structures
diff --git a/subsurface-core/dive.h b/subsurface-core/dive.h
index 204d34819..ae24b7409 100644
--- a/subsurface-core/dive.h
+++ b/subsurface-core/dive.h
@@ -339,8 +339,20 @@ struct dive {
int id; // unique ID for this dive
struct picture *picture_list;
int oxygen_cylinder_index, diluent_cylinder_index; // CCR dive cylinder indices
+ unsigned char git_id[20];
};
+static inline void invalidate_dive_cache(struct dive *dive)
+{
+ memset(dive->git_id, 0, 20);
+}
+
+static inline bool dive_cache_is_valid(const struct dive *dive)
+{
+ static const unsigned char null_id[20] = { 0, };
+ return !!memcmp(dive->git_id, null_id, 20);
+}
+
extern int get_cylinder_idx_by_use(struct dive *dive, enum cylinderuse cylinder_use_type);
extern void dc_cylinder_renumber(struct dive *dive, struct divecomputer *dc, int mapping[]);
@@ -755,6 +767,7 @@ extern int nr_weightsystems(struct dive *dive);
extern void add_cylinder_description(cylinder_type_t *);
extern void add_weightsystem_description(weightsystem_t *);
extern void remember_event(const char *eventname);
+extern void invalidate_dive_cache(struct dive *dc);
#if WE_DONT_USE_THIS /* this is a missing feature in Qt - selecting which events to display */
extern int evn_foreach(void (*callback)(const char *, bool *, void *), void *data);
diff --git a/subsurface-core/load-git.c b/subsurface-core/load-git.c
index a78082c07..a1f2d2031 100644
--- a/subsurface-core/load-git.c
+++ b/subsurface-core/load-git.c
@@ -1236,7 +1236,7 @@ static int dive_trip_directory(const char *root, const char *name)
*
* The root path will be of the form yyyy/mm[/tripdir],
*/
-static int dive_directory(const char *root, const char *name, int timeoff)
+static int dive_directory(const char *root, const git_tree_entry *entry, const char *name, int timeoff)
{
int yyyy = -1, mm = -1, dd = -1;
int h, m, s;
@@ -1314,6 +1314,7 @@ static int dive_directory(const char *root, const char *name, int timeoff)
finish_active_dive();
active_dive = create_new_dive(utc_mktime(&tm));
+ memcpy(active_dive->git_id, git_tree_entry_id(entry)->id, 20);
return GIT_WALK_OK;
}
@@ -1412,7 +1413,7 @@ static int walk_tree_directory(const char *root, const git_tree_entry *entry)
* two digits and a dash
*/
if (name[len-3] == ':' || name[len-3] == '=')
- return dive_directory(root, name, len-8);
+ return dive_directory(root, entry, name, len-8);
if (digits != 2)
return GIT_WALK_SKIP;
@@ -1470,6 +1471,12 @@ static int parse_divecomputer_entry(git_repository *repo, const git_tree_entry *
return 0;
}
+/*
+ * NOTE! The "git_id" for the dive is the hash for the whole dive directory.
+ * As such, it covers not just the dive, but the divecomputers and the
+ * pictures too. So if any of the dive computers change, the dive cache
+ * has to be invalidated too.
+ */
static int parse_dive_entry(git_repository *repo, const git_tree_entry *entry, const char *suffix)
{
struct dive *dive = active_dive;
diff --git a/subsurface-core/save-git.c b/subsurface-core/save-git.c
index 693abb623..e22019ab0 100644
--- a/subsurface-core/save-git.c
+++ b/subsurface-core/save-git.c
@@ -622,7 +622,7 @@ static int save_pictures(git_repository *repo, struct dir *dir, struct dive *div
return 0;
}
-static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm)
+static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *dive, struct tm *tm, bool cached_ok)
{
struct divecomputer *dc;
struct membuffer buf = { 0 }, name = { 0 };
@@ -631,6 +631,22 @@ static int save_one_dive(git_repository *repo, struct dir *tree, struct dive *di
/* Create dive directory */
create_dive_name(dive, &name, tm);
+
+ /*
+ * If the dive git ID is valid, we just create the whole directory
+ * with that ID
+ */
+ if (cached_ok && dive_cache_is_valid(dive)) {
+ git_oid oid;
+ git_oid_fromraw(&oid, dive->git_id);
+ ret = tree_insert(tree->files, mb_cstring(&name), 1,
+ &oid, GIT_FILEMODE_TREE);
+ free_buffer(&name);
+ if (ret)
+ return report_error("cached dive tree insert failed");
+ return 0;
+ }
+
subdir = new_directory(repo, tree, &name);
subdir->unique = 1;
free_buffer(&name);
@@ -747,7 +763,7 @@ static void verify_shared_date(timestamp_t when, struct tm *tm)
#define MIN_TIMESTAMP (0)
#define MAX_TIMESTAMP (0x7fffffffffffffff)
-static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *trip, struct tm *tm)
+static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *trip, struct tm *tm, bool cached_ok)
{
int i;
struct dive *dive;
@@ -781,7 +797,7 @@ static int save_one_trip(git_repository *repo, struct dir *tree, dive_trip_t *tr
/* Save each dive in the directory */
for_each_dive(i, dive) {
if (dive->divetrip == trip)
- save_one_dive(repo, subdir, dive, tm);
+ save_one_dive(repo, subdir, dive, tm, cached_ok);
}
return 0;
@@ -897,7 +913,7 @@ static void save_divesites(git_repository *repo, struct dir *tree)
}
}
-static int create_git_tree(git_repository *repo, struct dir *root, bool select_only)
+static int create_git_tree(git_repository *repo, struct dir *root, bool select_only, bool cached_ok)
{
int i;
struct dive *dive;
@@ -946,11 +962,11 @@ static int create_git_tree(git_repository *repo, struct dir *root, bool select_o
trip->index = 1;
/* Pass that new subdirectory in for save-trip */
- save_one_trip(repo, tree, trip, &tm);
+ save_one_trip(repo, tree, trip, &tm, cached_ok);
continue;
}
- save_one_dive(repo, tree, dive, &tm);
+ save_one_dive(repo, tree, dive, &tm, cached_ok);
}
return 0;
}
@@ -1176,6 +1192,7 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo
{
struct dir tree;
git_oid id;
+ bool cached_ok;
if (verbose)
fprintf(stderr, "git storage: do git save\n");
@@ -1183,6 +1200,12 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo
if (!create_empty) // so we are actually saving the dives
git_storage_update_progress(19, "start git save");
+ /*
+ * Check if we can do the cached writes - we need to
+ * have the original git commit we loaded in the repo
+ */
+ cached_ok = try_to_find_parent(saved_git_id, repo);
+
/* Start with an empty tree: no subdirectories, no files */
tree.name[0] = 0;
tree.subdirs = NULL;
@@ -1191,7 +1214,7 @@ int do_git_save(git_repository *repo, const char *branch, const char *remote, bo
if (!create_empty)
/* Populate our tree data structure */
- if (create_git_tree(repo, &tree, select_only))
+ if (create_git_tree(repo, &tree, select_only, cached_ok))
return -1;
if (verbose)