)]}'
{
  "commit": "5534f164d6aff567f7ea0b5b41e2e5bb35a0212c",
  "tree": "c5cfaedb059c82a61bf0972b743cd5470fdc7fb9",
  "parents": [
    "67e52a120b210f70b7a5de06996d9036f9f68011"
  ],
  "author": {
    "name": "Carlos Fernandez",
    "email": "carlosfsanz@meta.com",
    "time": "Thu May 07 09:00:33 2026 -0700"
  },
  "committer": {
    "name": "gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com",
    "email": "gerrit-scoped@luci-project-accounts.iam.gserviceaccount.com",
    "time": "Tue May 12 11:10:43 2026 -0700"
  },
  "message": "linkfile: Handle directory-to-symlink transitions safely\n\nWhen a manifest changes from individual linkfiles inside a directory\n(e.g. dest\u003d\".llms/rules\", dest\u003d\".llms/skills\") to a single linkfile\nfor the whole directory (e.g. dest\u003d\".llms\", src\u003d\"dot-llms\"), two\nthings need to happen:\n\n1. __linkIt must replace a real directory with a symlink.  Use\n   os.rmdir() instead of platform_utils.remove() for real directories.\n   rmdir only removes empty directories, so user-created content is\n   never deleted.\n\n2. UpdateCopyLinkfileList must handle the cleanup correctly:\n   - Use os.rmdir() for directories (safe for non-empty)\n   - Remove empty parent directories after cleaning old dests\n   - Retry _CopyAndLinkFiles for all projects, since in interleaved\n     sync mode _CopyAndLinkFiles runs before cleanup and may have\n     failed because the directory was not yet empty\n\nChange-Id: I0437b80beab98bce064cea81c11c47d699be91aa\nReviewed-on: https://gerrit-review.googlesource.com/c/git-repo/+/569243\nTested-by: Carlos Fernandez \u003ccarlosfsanz@meta.com\u003e\nReviewed-by: Mike Frysinger \u003cvapier@google.com\u003e\nReviewed-by: Gavin Mak \u003cgavinmak@google.com\u003e\nCommit-Queue: Carlos Fernandez \u003ccarlosfsanz@meta.com\u003e\n",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "45ffec78c43eb8b96fcc8d4126ddbdf6824ebbb9",
      "old_mode": 33188,
      "old_path": "platform_utils.py",
      "new_id": "58df6a9e2f0b9f40de1ae2c45e3671782b02513d",
      "new_mode": 33188,
      "new_path": "platform_utils.py"
    },
    {
      "type": "modify",
      "old_id": "f2fe7bc2a60ba87ebf4bb0760161be0010c2ed05",
      "old_mode": 33188,
      "old_path": "project.py",
      "new_id": "5f2a98e180bef3fbc0a3cf77efd9a6e00cbc6a1a",
      "new_mode": 33188,
      "new_path": "project.py"
    },
    {
      "type": "modify",
      "old_id": "2517694e7b7666a8e90d416b25aff889772bbd40",
      "old_mode": 33188,
      "old_path": "subcmds/sync.py",
      "new_id": "291bc624392275075d81f5cdd53d0f907973b739",
      "new_mode": 33188,
      "new_path": "subcmds/sync.py"
    },
    {
      "type": "modify",
      "old_id": "e89965391ab801c62470e36d16a52fd903f7055b",
      "old_mode": 33188,
      "old_path": "tests/test_platform_utils.py",
      "new_id": "919351e7fde7228f20f3ce56e67bb4a12ad3a4a8",
      "new_mode": 33188,
      "new_path": "tests/test_platform_utils.py"
    },
    {
      "type": "modify",
      "old_id": "1deec0726e09dfa6dea516201f0e45f4cef8e638",
      "old_mode": 33188,
      "old_path": "tests/test_project.py",
      "new_id": "728d5a54caf55d5b1126797612bf85f03698ba9e",
      "new_mode": 33188,
      "new_path": "tests/test_project.py"
    },
    {
      "type": "modify",
      "old_id": "669027c98383898206a5d8ecd6782eb9abae943d",
      "old_mode": 33188,
      "old_path": "tests/test_subcmds_sync.py",
      "new_id": "ef162392ba3646fb41f1e4f65040c9e26e63fbfc",
      "new_mode": 33188,
      "new_path": "tests/test_subcmds_sync.py"
    }
  ]
}
