Hi! Something like this has probably been answered before, but I'm having trouble figuring out what to search for.
I'm trying to write an editor for SmartGit's repository-grouping.yml
files. Their contents look something like this:
structure:
- name: code
children:
- name: github
children:
- name: imager
children:
- {name: imager, git: true, path: ~/code/github.com/imager-io/imager, path.absolute: /home/user/code/github.com/imager-io/imager}
- name: gitlab
children: []
recentlyUsed: [~/code/github.com/imager-io/imager]
ignored: []
Using serde
and the serde_yaml
I've got the file parsing into structs that look like:
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct RepoGroupingFile<'a> {
structure: Vec<StructureNode<'a>>,
#[serde(rename = "recentlyUsed")]
recently_used: Vec<String>,
ignored: Vec<String>,
}
#[serde(untagged)]
#[derive(Serialize, Deserialize, PartialEq, Debug)]
enum StructureNode<'a> {
Group(Group<'a>),
Repo(Repo<'a>),
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Group<'a> {
name: Cow<'a, str>,
children: Vec<StructureNode<'a>>,
expanded: bool,
}
#[derive(Serialize, Deserialize, PartialEq, Debug)]
struct Repo<'a> {
name: Cow<'a, str>,
git: bool,
path: Cow<'a, str>,
#[serde(rename = "path.absolute")]
path_absolute: Cow<'a, str>,
}
I'd like to be able to pass a path to a git repo, and create any Group and Repo notes (as necessary). In another language I'd loop through each level, creating additional nodes as necessary.
Eg (pseudocode - my current attempt is a broken mess):
/// structure is the structure vector from the file
/// hierarchy is the path split by separator eg: ['home,'user','test']
ensure_nodes(structure: Vec<StructureNode<'a>>, hierarchy: &mut VecDeque<String>) {
current_children = &structure
while let Some(current) = hierarchy.pop_front() {
if current_children contains node.name == current:
current_childern = node.children
continue
// create the node
new_node = StructureNode::Group(Group{})
current_children.push(new_node)
// grab the children vector from the element we just pushed onto the vec
current_children = ¤t_children.last().children
}
}
However, this approach runs afoul of the borrow checker, mostly around multiple mutable borrows of current_children
.
I was reading other approaches to mutable trees where nodes contain a vector of indicies of their children and you index into a vector containing the acual nodes. However, I'd rather not have to translate from the file representation to this editable representation and back again. I also considered rebuilding the entire structure every time (so everything is owned), but that didn't immediately seem like an easier solution.
Any advice would be greatly appreciated!