agendafs

A filesystem for your calendar.

git clone git://mccd.space/agendafs
commit ab15561d753748e017de59133dcdbc2497409000
parent 3c89cb5eb3007192cebb56b4a90df3e54fbdc4d2
Author: Marc Coquand <marc@coquand.email>
Date:   Fri, 27 Jun 2025 21:30:42 +0100

Correct child-parent linking

Diffstat:
Mjournal_entry.c | 106++++++++++++++++++++++++++++++++++++++++----------------------------------------
Mjournal_entry.h | 2+-
2 files changed, 54 insertions(+), 54 deletions(-)
diff --git a/journal_entry.c b/journal_entry.c
@@ -113,8 +113,11 @@ get_node_by_uuid(const char *target_uuid)
 		LOG("EMEM");
 		exit(1);
 	}
+	LOG("Looking for UID: '%s'", target_uuid);
+	LOG("Full filename: '%s'", filename_original);
 
 	tree_node *node = hashmap_get(entries_original_ics, filename_original);
+	LOG("Found it: %b", node != NULL);
 	return node;
 }
 bool
@@ -157,57 +160,38 @@ set_parent_child_relationship_to_component(icalcomponent *parent,
 	icalparameter *reltype_child =
 	    icalparameter_new_reltype(ICAL_RELTYPE_PARENT);
 	icalproperty_add_parameter(child_related_to_parent, reltype_child);
-	icalcomponent_add_property(child, child_related_to_parent);
 
-	icalproperty *parent_related_to_child =
-	    icalproperty_new_relatedto(icalcomponent_get_uid(child));
-	icalparameter *reltype_parent =
-	    icalparameter_new_reltype(ICAL_RELTYPE_CHILD);
-	icalproperty_add_parameter(parent_related_to_child, reltype_parent);
-
-	icalcomponent_add_property(parent, parent_related_to_child);
+	icalcomponent *inner =
+	    icalcomponent_get_first_component(child, ICAL_ANY_COMPONENT);
+	if (inner) {
+		icalcomponent_add_property(inner, child_related_to_parent);
+	}
+	else {
+		// or log an error, depending on your use case
+	}
 }
-
 void
 remove_parent_child_relationship_from_component(icalcomponent *parent,
 						icalcomponent *child)
 {
 
 	const char *parent_uid = icalcomponent_get_uid(parent);
-	const char *child_uid = icalcomponent_get_uid(child);
 
-	// Remove from child: RELATED-TO:parent_uid;RELTYPE=PARENT
+	icalcomponent *inner =
+	    icalcomponent_get_first_component(child, ICAL_ANY_COMPONENT);
+
 	icalproperty *prop =
-	    icalcomponent_get_first_property(child, ICAL_RELATEDTO_PROPERTY);
+	    icalcomponent_get_first_property(inner, ICAL_RELATEDTO_PROPERTY);
 	while (prop != NULL) {
 		icalproperty *next = icalcomponent_get_next_property(
-		    child, ICAL_RELATEDTO_PROPERTY);
+		    inner, ICAL_RELATEDTO_PROPERTY);
 		const char *value = icalproperty_get_relatedto(prop);
 		icalparameter *reltype = icalproperty_get_first_parameter(
 		    prop, ICAL_RELTYPE_PARAMETER);
 
 		if (value && strcmp(value, parent_uid) == 0 && reltype &&
 		    icalparameter_get_reltype(reltype) == ICAL_RELTYPE_PARENT) {
-			icalcomponent_remove_property(child, prop);
-			icalproperty_free(prop);
-		}
-
-		prop = next;
-	}
-
-	// Remove from parent: RELATED-TO:child_uid;RELTYPE=CHILD
-	prop =
-	    icalcomponent_get_first_property(parent, ICAL_RELATEDTO_PROPERTY);
-	while (prop != NULL) {
-		icalproperty *next = icalcomponent_get_next_property(
-		    parent, ICAL_RELATEDTO_PROPERTY);
-		const char *value = icalproperty_get_relatedto(prop);
-		icalparameter *reltype = icalproperty_get_first_parameter(
-		    prop, ICAL_RELTYPE_PARAMETER);
-
-		if (value && strcmp(value, child_uid) == 0 && reltype &&
-		    icalparameter_get_reltype(reltype) == ICAL_RELTYPE_CHILD) {
-			icalcomponent_remove_property(parent, prop);
+			icalcomponent_remove_property(inner, prop);
 			icalproperty_free(prop);
 		}
 
@@ -220,10 +204,12 @@ add_child_to_node(tree_node *parent, tree_node *child)
 {
 	// Root node, don't add relationship to component
 	if (is_root_node(parent)) {
+		LOG("Is root node, not adding relationship");
 		add_child(parent, child);
 		return;
 	}
 	else {
+		LOG("Adding parent and child relation");
 		struct journal_entry *p_entry = parent->data;
 		struct journal_entry *c_entry = child->data;
 		set_parent_child_relationship_to_component(p_entry->component,
@@ -246,9 +232,6 @@ free_segments(char **segments, size_t count)
 struct tree_node *
 get_node_by_path(struct tree_node *root, const char *path)
 {
-	if (!path)
-		return NULL;
-
 	if (strcmp(path, "/") == 0) {
 		LOG("Is ROOT %s", path);
 		return fuse_tree_root;
@@ -337,9 +320,12 @@ get_entry_from_fuse_path(const char *path)
 	}
 
 	struct journal_entry *entry = node->data;
-
-	LOG("Entry found: filename = '%s', original = '%s', path = '%s'",
-	    entry->filename, entry->filename_original, path);
+	char *ical_str = icalcomponent_as_ical_string_r(entry->component);
+	LOG("Entry found: filename = '%s', original = '%s', path = '%s', has "
+	    "nonroot parent= '%b'\n%s",
+	    entry->filename, entry->filename_original, path,
+	    !is_root_node(node->parent), ical_str);
+	free(ical_str);
 	return entry;
 }
 
@@ -549,10 +535,13 @@ load_journal_entry_from_ics_file(char *filename, struct journal_entry *entry)
 const char *
 get_parent_uid(icalcomponent *component)
 {
+	icalcomponent *inner =
+	    icalcomponent_get_first_component(component, ICAL_ANY_COMPONENT);
+
 	for (icalproperty *prop = icalcomponent_get_first_property(
-		 component, ICAL_RELATEDTO_PROPERTY);
+		 inner, ICAL_RELATEDTO_PROPERTY);
 	     prop != NULL; prop = icalcomponent_get_next_property(
-			       component, ICAL_RELATEDTO_PROPERTY)) {
+			       inner, ICAL_RELATEDTO_PROPERTY)) {
 		const char *reltype =
 		    icalproperty_get_parameter_as_string(prop, "RELTYPE");
 		if (reltype && strcasecmp(reltype, "PARENT") == 0) {
@@ -562,7 +551,6 @@ get_parent_uid(icalcomponent *component)
 
 	return NULL;
 }
-
 // Initializes values
 // Should only be run once at the start
 void
@@ -619,12 +607,19 @@ load_journal_entries()
 	LOG("Setting up directories");
 
 	// Second pass, reattach according to parent-child
-	for (size_t i = 0; i < fuse_tree_root->child_count; i++) {
-		tree_node *child = fuse_tree_root->children[i];
+	size_t n_keys = 0;
+	char **keys = hashmap_get_keys(entries_original_ics, &n_keys);
+	for (size_t i = 0; i < n_keys; i++) {
+		const char *filename = keys[i];
+		tree_node *child = hashmap_get(entries_original_ics, filename);
 		struct journal_entry *entry = child->data;
 
 		const char *parent_uid = get_parent_uid(entry->component);
+		LOG("Looking up entry %s, %s", entry->filename_original,
+		    entry->filename);
 		if (parent_uid) {
+			LOG("Has parent");
+
 			tree_node *parent = get_node_by_uuid(parent_uid);
 			if (parent) {
 				detach_tree_node(child);
@@ -636,6 +631,7 @@ load_journal_entries()
 			}
 		}
 	}
+	free(keys);
 	LOG("Done");
 	// TODO: Handle duplicates by changing file name to .1, .2 etc.
 }
@@ -799,6 +795,18 @@ do_journal_entry_rename(const char *old, const char *new)
 	if (!old_filename)
 		return -EINVAL;
 
+	char *parent_path = NULL;
+	get_parent_path(new, &parent_path);
+	LOG("PARENT PATH: %s", parent_path);
+	tree_node *new_parent_node =
+	    get_node_by_path(fuse_tree_root, parent_path);
+	free(parent_path);
+
+	if (new_parent_node == NULL) {
+
+		return -EINVAL;
+	}
+
 	char *new_summary = strdup(new_filename);
 
 	// Remove everything after extension
@@ -833,15 +841,8 @@ do_journal_entry_rename(const char *old, const char *new)
 		return -EIO;
 	}
 
-	char *parent_path = NULL;
-	get_parent_path(new, &parent_path);
-	LOG("PARENT PATH: %s", parent_path);
-	tree_node *new_parent_node =
-	    get_node_by_path(fuse_tree_root, parent_path);
 	free(parent_path);
 
-	move_node(old_parent_node, new_parent_node, entry_node);
-
 	// TODO: Filename must be unique
 	asprintf(&new_entry->filename, "%s", new_filename);
 	LOG("New filename is now %s", new_filename);
@@ -854,7 +855,7 @@ do_journal_entry_rename(const char *old, const char *new)
 
 	icalcomponent_set_summary(new_entry->component, new_summary);
 	entry_node->data = new_entry;
-	write_entry_to_ical_file(new_entry);
+	move_node(old_parent_node, new_parent_node, entry_node);
 
 	free_journal_entry(old_entry);
 	free(new_copy);
@@ -892,7 +893,6 @@ create_vjournal_entry(char *summary)
 	char *id = create_new_unique_ics_uid();
 
 	icalcomponent_add_property(journal, icalproperty_new_uid(id));
-
 	icalcomponent_add_property(journal,
 				   icalproperty_new_class(ICAL_CLASS_PRIVATE));
 
diff --git a/journal_entry.h b/journal_entry.h
@@ -26,7 +26,7 @@
 // et.c.
 struct journal_entry {
 	// filename is full path relative to fuse directory
-	// I.E. hello world.txt
+	// I.E. hello world
 	char *filename;
 	// filename_original is the relative path to ICS_DIR
 	// I.E. 910319208nrao19p.ics