Repository navigation
Conversation
mathjazz
left a comment
There was a problem hiding this comment.
Thanks for the patch! Left a few comments inline.
| removed_paths = { | ||
| get_db_path(paths, join(checkout.path, co_path)) for co_path in checkout.removed | ||
| } | ||
| if isinstance(paths, L10nConfigPaths): |
There was a problem hiding this comment.
Marking entities obsolete here can't be undone later. When a path comes back, update_resources() un-obsoletes the resource but not its entities, so it creates a second copy of every Entity, and the old translations, comments and reviews stay stuck on the hidden ones.
There was a problem hiding this comment.
Is this effectively #4128? Based on your comment there, I'm applying a content (value & properties) match that is LIFO/newest copy. Also adding a "Restored" log.
| get_db_path(paths, join(checkout.path, co_path)) for co_path in checkout.removed | ||
| } | ||
| if isinstance(paths, L10nConfigPaths): | ||
| ref_db_paths = {get_db_path(paths, ref_path) for ref_path in paths.ref_paths} |
There was a problem hiding this comment.
ref_paths is just whatever the glob matched this run, so a typo in reference (or a source folder moved one commit before the config is updated) makes it empty and wipes out the whole project in one sync.
Shall we refuse to obsolete when the list covers all or nearly all resources?
| current = set(project.resources.current().values_list("path", flat=True)) | ||
| for ref_path in paths.ref_paths: | ||
| if ( | ||
| relpath(ref_path, paths.ref_root) in current |
There was a problem hiding this comment.
This skips references we already track, so if only the l10n target moves (e.g. {locale}/a.ftl → l10n/{locale}/a.ftl), the files at the new location never get added to target.changed and their translations aren't picked up.
eemeli
left a comment
There was a problem hiding this comment.
A partial review, happy to have Matjaž take the lead here.
| ref_db_paths = {get_db_path(paths, ref_path) for ref_path in paths.ref_paths} | ||
| current_paths = set(project.resources.current().values_list("path", flat=True)) | ||
| unreferenced_paths = current_paths - ref_db_paths | ||
| if len(unreferenced_paths) > 0.9 * len(current_paths): |
There was a problem hiding this comment.
This magic number should be a constant defined near the top of the file.
| } | ||
| if isinstance(paths, L10nConfigPaths): | ||
| ref_db_paths = {get_db_path(paths, ref_path) for ref_path in paths.ref_paths} | ||
| current_paths = set(project.resources.current().values_list("path", flat=True)) |
There was a problem hiding this comment.
This is the second time you end up doing the same DB query during the same sync; we should avoid that.
| ent.obsolete = False | ||
| ent.date_obsoleted = None | ||
| restored[key] = ent | ||
| Entity.objects.bulk_update(restored.values(), ["obsolete", "date_obsoleted"]) |
There was a problem hiding this comment.
Entity deobsoletion seems like quite a bit of scope creep for work under "Project config: preserve resources and localized files". I'm pretty sure this ought to get left out at least for now, and addressed separately -- there are almost certainly side effects that need to be accounted for.
There was a problem hiding this comment.
Alright, let's leave that out.
Co-authored-by: Eemeli Aro <eemeli@gmail.com>
mathjazz
left a comment
There was a problem hiding this comment.
This looks good, nice work!
Co-authored-by: Eemeli Aro <eemeli@gmail.com>
Co-authored-by: Eemeli Aro <eemeli@gmail.com>
| tgt_path = paths.format_target_path(tgt_template, locale) | ||
| if tracked and ( | ||
| ref_path in renamed_refs | ||
| or prev_paths is None | ||
| or prev_paths.target(ref_path, locale=locale)[0] == tgt_path | ||
| ): | ||
| continue | ||
| if has_current_resource: | ||
| prev_tgt_path, _ = prev_paths.target(ref_path, locale=locale) | ||
| if prev_tgt_path == tgt_path: | ||
| continue |
There was a problem hiding this comment.
If the paths match for any locale, doesn't that mean that they'll match for every locale? Could you not compare the template strings instead, outside this loop?
There was a problem hiding this comment.
Uhhh... yes. I also just realized that the previous approach was a little inefficient...
Changing now.
| config_current_paths: set[str] = set() | ||
| if isinstance(paths, L10nConfigPaths): | ||
| config_current_paths = { | ||
| renamed_db_paths.get(path, path) | ||
| for path in project.resources.current().values_list("path", flat=True) | ||
| } |
There was a problem hiding this comment.
The term "current" is confusing me here, because it's not clear if it's a point in time before the sync started, some point during the sync, or after the sync has completed.
Let's avoid it, and use something more verbose but explicit like config_db_paths_with_renames.
| for ref_path in paths.ref_paths: | ||
| if not isfile(ref_path) or not is_inside(source.path, ref_path): | ||
| continue | ||
| has_current_resource = relpath(ref_path, paths.ref_root) in config_current_paths |
There was a problem hiding this comment.
This is definitely better, but still a bit confusing, again I think driven by the "current" term being unclear.
Would something like this be accurate?
| has_current_resource = relpath(ref_path, paths.ref_root) in config_current_paths | |
| is_new = relpath(ref_path, paths.ref_root) not in config_current_paths |
Note that the conditional is inverted here.
| if not has_current_resource and ref_path not in src_changed: | ||
| source.changed.append(relpath(ref_path, source.path)) | ||
| if has_current_resource and ref_path in renamed_refs: | ||
| continue |
There was a problem hiding this comment.
Continuing with the previous suggestion:
| if not has_current_resource and ref_path not in src_changed: | |
| source.changed.append(relpath(ref_path, source.path)) | |
| if has_current_resource and ref_path in renamed_refs: | |
| continue | |
| if is_new: | |
| if ref_path not in src_changed: | |
| source.changed.append(relpath(ref_path, source.path)) | |
| else: | |
| if ref_path in renamed_refs: | |
| continue |
Fix #2844
Fix #4385
paths.ref_pathsnow go throughmark_as_obsolete().