ProjectConfig: Write resolved groups to file

project.config references group names from the groups file.
These names are local to the project. The groups file links the
local name to a global groups UUID.

Renaming a group makes Gerrit go through all projects and try to
rename the local group names. This commit fixes a bug that would
make Gerrit only change the groups file, but not the project.config
file. This lead to half-baked renames that can break ACLs.

Change-Id: I46993b4838ddfa700acb79911713aa42cc026590
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index 54d9176..89038e2 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -1425,7 +1425,7 @@
           if (group.getUUID() != null) {
             keepGroups.add(group.getUUID());
           }
-          rules.add(rule.asString(needRange));
+          rules.add(rule.toBuilder().setGroup(group).build().asString(needRange));
         }
         rc.setStringList(CAPABILITY, null, permission.getName(), rules);
       }
@@ -1470,7 +1470,7 @@
           if (group.getUUID() != null) {
             keepGroups.add(group.getUUID());
           }
-          rules.add(rule.asString(needRange));
+          rules.add(rule.toBuilder().setGroup(group).build().asString(needRange));
         }
         rc.setStringList(ACCESS, refName, permission.getName(), rules);
       }
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 0d94ce6..436ad7c 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -113,6 +113,7 @@
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.stream.Stream;
 import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 import org.eclipse.jgit.junit.TestRepository;
@@ -704,6 +705,36 @@
   }
 
   @Test
+  public void renamingGroupChangesProjectConfigs() throws Exception {
+    String name = name("Name1");
+    GroupInfo group = gApi.groups().create(name).get();
+
+    // Use group in a permission
+    projectOperations
+        .project(project)
+        .forUpdate()
+        .add(allow(Permission.READ).ref(RefNames.REFS_CONFIG).group(AccountGroup.uuid(group.id)))
+        .update();
+    Optional<String> beforeRename =
+        projectCache.get(project).get().getLocalGroups().stream()
+            .filter(g -> g.getUUID().get().equals(group.id))
+            .map(GroupReference::getName)
+            .findAny();
+    // Groups created with ProjectOperations always have their UUID as local name
+    assertThat(beforeRename).hasValue(group.id);
+
+    String newName = name("Name2");
+    gApi.groups().id(name).name(newName);
+
+    Optional<String> afterRename =
+        projectCache.get(project).get().getLocalGroups().stream()
+            .filter(g -> g.getUUID().get().equals(group.id))
+            .map(GroupReference::getName)
+            .findAny();
+    assertThat(afterRename).hasValue(newName);
+  }
+
+  @Test
   public void groupDescription() throws Exception {
     String name = name("group");
     gApi.groups().create(name);