)]}'
{
  "commit": "286739e356c69badf698f0f735b30607bec4f25e",
  "tree": "32e99fcd20483fd18d1d717ec785d4b58ac5ea17",
  "parents": [
    "7fffa89cbdf10eabc466c3053bf9e7bee29a9876"
  ],
  "author": {
    "name": "kevan Jahanshahi",
    "email": "kevan@jahia.com",
    "time": "Thu Nov 12 09:14:27 2026 +0100"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Thu Nov 12 09:14:27 2026 +0100"
  },
  "message": "FELIX-6812 Follow-up: escape the pid in the service.pid filter (#563)\n\n* FELIX-6812 Follow-up: escape the pid in the service.pid filter\n\nFELIX-6812 replaced getConfiguration(pid, \"?\") with a listConfigurations call,\nand it builds the filter by concatenating the pid. A pid is not a filter-safe\nvalue, and the class already escapes one in findExistingConfiguration.\n\nA pid holding an asterisk builds a substring filter. listConfigurations then\nreturns configurations the event was not about, and ConfigInstaller writes the\nfirst of them back to that other configuration\u0027s file. A pid holding a\nparenthesis throws InvalidSyntaxException instead, which the catch reports as a\nfailure to save, so the configuration is never written back.\n\nescapeFilterValue left the backslash alone, although the OSGi filter grammar\nreserves it. A pid holding a backslash therefore stayed ambiguous after the\nescaping. The backslash is escaped first, or the escapes added after it would be\nescaped a second time.\n\nThe method now matches literals rather than patterns. It compiled four patterns\nper call, and FELIX-6812 moved it from findExistingConfiguration, called once per\nfile install, to doConfigurationEvent, called for every configuration event.\n\nTwo tests raise CM_UPDATED for a pid holding an asterisk and for a pid holding a\nbackslash, and each one fails when its escape is removed.\n\n* FELIX-6812 Follow-up: the two tests the change left green and empty\n\nFELIX-6812 moved the CM_UPDATED path from getConfiguration to listConfigurations,\nand two tests kept the expectations of the older call. Neither test calls\nEasyMock.verify, so an expectation nothing consumes fails nothing.\n\ntestUseExistingConfigAndObserveCMDeleted expects listConfigurations for any\nargument and answers null. The handler then returns before it reads anything, so\nthe test asserts nothing at all while it passes. It now expects the filter the\nhandler builds and answers with a configuration.\n\ntestUseExistingConfigWithFileinstallFilenameAndObserveCMDeleted still expects\ngetConfiguration and update. The CM_UPDATED path writes the file and calls no\nmethod on the configuration, and getConfiguration is reachable from setConfig\nonly, which this test never calls.\n\nBoth tests verify their mocks now, which is what makes an expectation\nload-bearing. The dead expectations go, and the Capture that fed update goes\nwith them. Adding the verify call before removing the expectations fails on\nConfiguration.update, which is the measurement behind this commit.",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "020ee0bb52a463f5c278e7d875a137f0fda9a7e9",
      "old_mode": 33188,
      "old_path": "fileinstall/src/main/java/org/apache/felix/fileinstall/internal/ConfigInstaller.java",
      "new_id": "ca600596e5d2371dd7eca5428ecdbc1926bbeb43",
      "new_mode": 33188,
      "new_path": "fileinstall/src/main/java/org/apache/felix/fileinstall/internal/ConfigInstaller.java"
    },
    {
      "type": "modify",
      "old_id": "f423379041663cdd6114db589a248825cb7a44dd",
      "old_mode": 33188,
      "old_path": "fileinstall/src/test/java/org/apache/felix/fileinstall/internal/ConfigInstallerTest.java",
      "new_id": "3e8c011ebb89e95df09d3f5cc5011cdb326f0f2a",
      "new_mode": 33188,
      "new_path": "fileinstall/src/test/java/org/apache/felix/fileinstall/internal/ConfigInstallerTest.java"
    }
  ]
}
