Skip to content

Commit a0b5c30

Browse files
author
Vladimir Kotal
authored
Project message set/get (#2153)
approaches #2147
1 parent aeb0b34 commit a0b5c30

File tree

3 files changed

+155
-11
lines changed

3 files changed

+155
-11
lines changed

src/org/opensolaris/opengrok/configuration/messages/ProjectMessage.java

Lines changed: 94 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import java.util.TreeSet;
3434
import java.util.logging.Level;
3535
import java.util.logging.Logger;
36+
import java.util.regex.Matcher;
37+
import java.util.regex.Pattern;
3638
import java.util.stream.Collectors;
3739
import org.opensolaris.opengrok.configuration.Group;
3840
import org.opensolaris.opengrok.configuration.Project;
@@ -43,6 +45,7 @@
4345
import org.opensolaris.opengrok.history.RepositoryInfo;
4446
import org.opensolaris.opengrok.index.IndexDatabase;
4547
import org.opensolaris.opengrok.logger.LoggerFactory;
48+
import org.opensolaris.opengrok.util.ClassUtil;
4649
import org.opensolaris.opengrok.util.ForbiddenSymlinkException;
4750
import org.opensolaris.opengrok.util.IOUtils;
4851

@@ -56,6 +59,16 @@ public class ProjectMessage extends Message {
5659

5760
private static final Logger LOGGER = LoggerFactory.getLogger(ProjectMessage.class);
5861

62+
/**
63+
* Pattern describes the java variable name and the assigned value.
64+
* Examples:
65+
* <ul>
66+
* <li>variable = true</li>
67+
* <li>stopOnClose = 10</li>
68+
* </ul>
69+
*/
70+
private static final Pattern VARIABLE_PATTERN = Pattern.compile("([a-z_]\\w*) = (.*)");
71+
5972
/**
6073
* Perform additional validation. This cannot be done in validate()
6174
* because it does not have access to the currently used RuntimeEnvironment.
@@ -102,12 +115,24 @@ private List<RepositoryInfo> getRepositoriesInDir(RuntimeEnvironment env,
102115
env.getIgnoredNames()));
103116
}
104117

118+
private String getCommand() {
119+
String command = getText();
120+
121+
// get/set need special treatment since the text is overloaded with actual
122+
// command and its contents.
123+
if (command.startsWith("set ") || command.startsWith("get ")) {
124+
command = getText().substring(0, 3);
125+
}
126+
127+
return command;
128+
}
129+
105130
@Override
106131
protected byte[] applyMessage(RuntimeEnvironment env) throws Exception {
107-
String command = getText();
132+
String command = getCommand();
108133

109134
validateMore(env);
110-
135+
111136
switch (command) {
112137
case "add":
113138
for (String projectName : getTags()) {
@@ -248,6 +273,65 @@ protected byte[] applyMessage(RuntimeEnvironment env) throws Exception {
248273

249274
env.refreshDateForLastIndexRun();
250275
break;
276+
case "set":
277+
Matcher matcher = VARIABLE_PATTERN.matcher(getText().substring(4));
278+
if (!matcher.find()) {
279+
// invalid pattern
280+
throw new IOException(
281+
String.format("The pattern \"%s\" does not match \"%s\".",
282+
VARIABLE_PATTERN.toString(),
283+
getText()));
284+
}
285+
286+
// Perform a best effort on setting the project properties.
287+
// If property cannot be set for one project, keep going on.
288+
List<String> projectsDone = new ArrayList<>();
289+
for (String projectName : getTags()) {
290+
Project project;
291+
if ((project = env.getProjects().get(projectName)) != null) {
292+
// Set the property.
293+
ClassUtil.invokeSetter(
294+
project,
295+
matcher.group(1), // field
296+
matcher.group(2) // value
297+
);
298+
299+
// Refresh repositories for this project as well.
300+
List<RepositoryInfo> riList = env.getProjectRepositoriesMap().get(project);
301+
if (riList != null) {
302+
for (RepositoryInfo ri : riList) {
303+
Repository repo = getRepository(ri, false);
304+
305+
// set the property
306+
ClassUtil.invokeSetter(
307+
repo,
308+
matcher.group(1), // field
309+
matcher.group(2) // value
310+
);
311+
}
312+
}
313+
314+
projectsDone.add(projectName);
315+
} else {
316+
LOGGER.log(Level.WARNING, "cannot find project " +
317+
projectName + " to set a property");
318+
}
319+
}
320+
321+
return String.format("Variable \"%s\" set to \"%s\" for projects: %s",
322+
matcher.group(1), matcher.group(2),
323+
String.join(",", projectsDone)).getBytes();
324+
case "get":
325+
for (String projectName : getTags()) {
326+
Project project = env.getProjects().get(projectName);
327+
if (project != null) {
328+
return ClassUtil.invokeGetter(project, getText().substring(4)).getBytes();
329+
} else {
330+
LOGGER.log(Level.WARNING, "cannot find project " +
331+
projectName + " to get a property");
332+
}
333+
}
334+
break;
251335
case "list":
252336
return (env.getProjectNames().stream().collect(Collectors.joining("\n")).getBytes());
253337
case "list-indexed":
@@ -257,8 +341,8 @@ protected byte[] applyMessage(RuntimeEnvironment env) throws Exception {
257341
List<String> repos = new ArrayList<>();
258342

259343
for (String projectName : getTags()) {
260-
Project project;
261-
if ((project = env.getProjects().get(projectName)) == null) {
344+
Project project = env.getProjects().get(projectName);
345+
if (project == null) {
262346
continue;
263347
}
264348
List<RepositoryInfo> infos = env.getProjectRepositoriesMap().
@@ -302,10 +386,10 @@ protected byte[] applyMessage(RuntimeEnvironment env) throws Exception {
302386
*/
303387
@Override
304388
public void validate() throws Exception {
305-
String command = getText();
389+
String command = getCommand();
306390
Set<String> allowedText = new TreeSet<>(Arrays.asList("add", "delete",
307391
"list", "list-indexed", "indexed", "get-repos",
308-
"get-repos-type"));
392+
"get-repos-type", "get", "set"));
309393

310394
// Text field carries the command.
311395
if (command == null) {
@@ -319,6 +403,10 @@ public void validate() throws Exception {
319403
throw new Exception("The message must contain a tag (project name(s))");
320404
}
321405

406+
if (command.equals("get") && getTags().size() != 1) {
407+
throw new Exception("The \"get\" command can take only one project.");
408+
}
409+
322410
super.validate();
323411
}
324412
}

test/org/opensolaris/opengrok/configuration/messages/ProjectMessageTest.java

Lines changed: 52 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,9 @@
4848
import org.opensolaris.opengrok.history.HistoryGuru;
4949
import org.opensolaris.opengrok.history.MercurialRepository;
5050
import org.opensolaris.opengrok.history.MercurialRepositoryTest;
51+
import org.opensolaris.opengrok.history.Repository;
5152
import org.opensolaris.opengrok.history.RepositoryFactory;
53+
import static org.opensolaris.opengrok.history.RepositoryFactory.getRepository;
5254
import org.opensolaris.opengrok.history.RepositoryInfo;
5355
import org.opensolaris.opengrok.history.SubversionRepository;
5456
import org.opensolaris.opengrok.index.IndexDatabase;
@@ -62,6 +64,8 @@
6264
* @author Vladimir Kotal
6365
*/
6466
@ConditionalRun(RepositoryInstalled.MercurialInstalled.class)
67+
@ConditionalRun(RepositoryInstalled.GitInstalled.class)
68+
@ConditionalRun(RepositoryInstalled.SubvsersionInstalled.class)
6569
public class ProjectMessageTest {
6670

6771
RuntimeEnvironment env;
@@ -73,10 +77,6 @@ public class ProjectMessageTest {
7377

7478
@Before
7579
public void setUp() throws IOException {
76-
Assume.assumeTrue(new MercurialRepository().isWorking());
77-
Assume.assumeTrue(new SubversionRepository().isWorking());
78-
Assume.assumeTrue(new GitRepository().isWorking());
79-
8080
repository = new TestRepository();
8181
repository.create(HistoryGuru.class.getResourceAsStream(
8282
"repositories.zip"));
@@ -149,7 +149,6 @@ public void testValidate() {
149149
* from configuration. Ideally, this should test all properties of Project.
150150
* @throws Exception
151151
*/
152-
@ConditionalRun(RepositoryInstalled.GitInstalled.class)
153152
@Test
154153
public void testAddInherit() throws Exception {
155154
Assert.assertTrue(env.getRepositories().isEmpty());
@@ -495,4 +494,52 @@ public void testGetRepos() throws Exception {
495494
out = new String(m.apply(env));
496495
Assert.assertEquals("Mercurial", out);
497496
}
497+
498+
@Test
499+
public void testSetGet() throws Exception {
500+
Assert.assertTrue(env.isHandleHistoryOfRenamedFiles());
501+
List<String> projects = new ArrayList<>();
502+
projects.add("mercurial");
503+
projects.add("git");
504+
Message m;
505+
506+
// Add the projects.
507+
m = new ProjectMessage();
508+
m.setText("add");
509+
for (String proj : projects) {
510+
m.addTag(proj);
511+
}
512+
m.apply(env);
513+
Assert.assertEquals(2, env.getProjectList().size());
514+
515+
// Change their property.
516+
m = new ProjectMessage();
517+
m.setText("set handleRenamedFiles = false");
518+
for (String proj : projects) {
519+
m.addTag(proj);
520+
}
521+
m.apply(env);
522+
523+
// Verify the property was set on each project and its repositories.
524+
for (String proj : projects) {
525+
Project project = env.getProjects().get(proj);
526+
Assert.assertNotNull(project);
527+
Assert.assertFalse(project.isHandleRenamedFiles());
528+
List<RepositoryInfo> riList = env.getProjectRepositoriesMap().get(project);
529+
Assert.assertNotNull(riList);
530+
for (RepositoryInfo ri : riList) {
531+
Repository repo = getRepository(ri, false);
532+
Assert.assertFalse(repo.isHandleRenamedFiles());
533+
}
534+
}
535+
536+
// Verify the property can be retrieved via message.
537+
for (String proj : projects) {
538+
m = new ProjectMessage();
539+
m.setText("get handleRenamedFiles");
540+
m.addTag(proj);
541+
String out = new String(m.apply(env));
542+
Assert.assertEquals("false", out);
543+
}
544+
}
498545
}

tools/Messages

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@ Usage()
9999
echo " - \"list-indexed\" - list indexed projects"
100100
echo " - \"get-repos\" - get list of repositories in the form of relative paths to source root for given project(s)"
101101
echo " - \"get-repos-type\" - get repository type(s) for given project(s)"
102+
echo " - \"set\" - sets a particular project property (only primitive types)"
103+
echo " in the webapp."
104+
echo " Examples:"
105+
echo " tabSize = 8"
106+
echo " handleRenamedFiles = true"
107+
echo " Returns text describing the action."
108+
echo " The change is NOT persistent when reindex or redeploy!"
109+
echo " - \"get\" retrieves the particular per project property (only primitive types)"
110+
echo " Returns string representation of the property."
102111
echo " repository:"
103112
echo " - repository paths relative to source root are specified as <tags>"
104113
echo " - command is specified in message <text>:"

0 commit comments

Comments
 (0)