Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #32: Main #57

Merged
merged 1 commit into from
Jul 27, 2017
Merged

Issue #32: Main #57

merged 1 commit into from
Jul 27, 2017

Conversation

Luolc
Copy link
Contributor

@Luolc Luolc commented Jul 20, 2017

#32

I don't know what to add in pom.xml. I failed to run the project by java -jar ... way.

I haven't handle any exceptions of components now, how should be present the exception message for user? Should we have a [ERROR] prefix or smth like this?

@rnveach
Copy link
Member

rnveach commented Jul 20, 2017

I failed to run the project by java -jar ... way.

I will create the configuration for the all jar.
Edit: you added it, I'll see what is wrong.

how should be present the exception message for user?

I am fine throwing the exception all the way past main.

Copy link
Member

@rnveach rnveach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need an issue on code coverage in POM.

pom.xml Outdated
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.puppycrawl.tools.checkstyle.Main</mainClass>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong package.

/**
* Utility class, contains main function and its auxiliary routines.
* @author LuoLiangchen
*/
public final class Main {
/** Option name of repository path. */
private static final String OPT_REPO = "repo";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add short names and long names.

https://github.com/checkstyle/contribution/blob/master/checkstyle-tester/diff.groovy#L44
Try to make similar options the same as the groovy scripts, that way there is less a learning curve.
This sound good?

Copy link
Contributor Author

@Luolc Luolc Jul 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this changes:
repo => localGitRepo, and short opt is r
branch => patchBranch and short opt is p

Do we really need a parameter of baseBranch? Is it possible that the base branch is not master? If yes, then git components need to be updated as well.

The option name of checkstyle-tester path is being discussed in the post below.

Short opts are defined in createOptions directly. Need I create static final field instead of writing them in plain text in createOptions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really need a parameter of baseBranch?

No. I was only recommending changes for existing parameters.

Need I create static final field instead of writing them in plain text in createOptions?

I am fine without this for now.

private static final String OPT_BRANCH = "branch";

/** Option name of checkstyle-tester path. */
private static final String OPT_TESTER = "tester";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

contribution is the name of the repo. checkstyle-tester is the name of the folder.
Can we choose a better, more precise name?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So checkstyleTester?


try {
cmd = parser.parse(options, args);
final String repoPath = cmd.getOptionValue(OPT_REPO);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All paths and other fields need to be validated if they are entered.
Paths must exist and be a directory, etc..
etc..

System.out.println("report generated at " + report.getAbsolutePath());
}
}
catch (ParseException ex) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's just throw exception past main.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is OK to throw exceptions from components.

But this is exactly a argument format exception, it is only caused by user input 1. wrong format 2.missing arguments 3. wrong argument number etc. And in this case we need to print help message(by formatter.printHelp) and tell user how to use this tool. So I think this catch is necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. wrong format 2.missing arguments 3. wrong argument number etc.

Than why is it covering everything if it is only for user input? What lines are throwing this?

Copy link
Contributor Author

@Luolc Luolc Jul 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The first line in catch block. I will update this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated. Only the parsing line in try block now.

ModuleUtils.setNameToModuleExtractInfo(extractInfos);
final List<ModuleInfo> moduleInfos = ModuleCollector.generate(changes);
final String configFileName =
String.format("config-%s-%d.xml", branch, System.currentTimeMillis());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we are going to format it, can we do date and time instead of milliseconds?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done.

final String branch = cmd.getOptionValue(OPT_BRANCH);
final boolean stopAfterGenerateConfig = cmd.hasOption(OPT_STOP_AFTER_GENERATE_CONFIG);

final File config = generateConfig(repoPath, branch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this and lines below it should all be in runRegression.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is runRegression? Do you mean create a new method with name runRegression?

final String branch = cmd.getOptionValue(OPT_PATCH_BRANCH);
final boolean stopAfterGenerateConfig = cmd.hasOption(OPT_STOP_AFTER_GENERATE_CONFIG);

final File config = generateConfig(repoPath, branch);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is runRegression? Do you mean create a new method with name runRegression?

yes, and move these liens into it.
I want separation between validating input and running of regression.
Similar to https://github.com/checkstyle/checkstyle/blob/master/src/main/java/com/puppycrawl/tools/checkstyle/Main.java#L381 and https://github.com/checkstyle/checkstyle/blob/master/src/main/java/com/puppycrawl/tools/checkstyle/Main.java#L287 .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Add a validateArguments and runRegression

@@ -4,6 +4,9 @@
"http://www.puppycrawl.com/dtds/import_control_1_1.dtd">

<import-control pkg="com.github.checkstyle.regression">
<allow pkg="org.apache.commons.cli" local-only="true"/>
<allow pkg="com.github.checkstyle.regression" local-only="true"/>
<allow pkg="java.text"/>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this local only too for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 23, 2017

We need an issue on code coverage in POM.

#58

checkstyle-tester is the name of the folder.
Can we choose a better, more precise name?

Now it is named as checkstyleTester. Is that ok?

I forget to reply done to some of the reviews before, sorry.

@rnveach
Copy link
Member

rnveach commented Jul 23, 2017

Now it is named as checkstyleTester. Is that ok?

Shouldn't it end with path to better signify we want the path?

throw new IllegalArgumentException(
"path of local git repo must exist and be a directory");
}
if (!args.stopAfterGenerateConfig() && !existAndIsDirectory(args.testerPath().get())) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I don't give any value for testerPath, will args.testerPath() return null?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional.get() would throw an exception if we don't have a value. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/Optional.java#Optional.get%28%29

I would update this code.

final Arguments arguments = ImmutableArguments.builder()
.repoPath(cmd.getOptionValue(OPT_LOCAL_GIT_REPO))
.branch(cmd.getOptionValue(OPT_PATCH_BRANCH))
.testerPath(cmd.getOptionValue(OPT_CHECKSTYLE_TESTER))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use full name for this one, testerPath. It just seems slightly off.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

}
if (!args.stopAfterGenerateConfig() && !existAndIsDirectory(args.testerPath().get())) {
throw new IllegalArgumentException(
"path of checkstyle tester must exist and be a directory");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I don't give tester path, this statement will look odd as it doesn't also say it is a required field.

private static void validateArguments(Arguments args) {
if (!existAndIsDirectory(args.repoPath())) {
throw new IllegalArgumentException(
"path of local git repo must exist and be a directory");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if I don't give repo path, this statement will look odd as it doesn't also say it is a required field.

* @return the generated config file
* @throws Exception generation failure
*/
private static File generateConfig(String repoPath, String branch)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move closer to runRegression. it is like a child method.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


/** Represents the CLI arguments. */
@Value.Immutable
/* default */ interface Arguments {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the default comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would have a PMD failure without this. Rule:CommentDefaultAccessModifier
https://pmd.github.io/pmd-5.4.0/pmd-java/rules/java/comments.html#CommentDefaultAccessModifier

We need package-private here. private and protected can't be inherited by immutables and public is not necessary.
We have another choice that updating pmd.xml to ignore this, instead of this comment.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, ignore this then. we will leave it for now.

* @return true if file exists and is a directory
*/
private static boolean existAndIsDirectory(String path) {
final File file = new File(path);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if path can be null or empty string, won't this incorrectly return that it exists?
verify first that null or empty string can get into here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can't be null, but could be empty if we write smth like path="" in CLI.

Check is added.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 24, 2017

@rnveach

Now it is named as checkstyleTester. Is that ok?

Shouldn't it end with path to better signify we want the path?

Update to checkstyleTesterPath

if I don't give repo path, this statement will look odd as it doesn't also say it is a required field.
if I don't give tester path, this statement will look odd as it doesn't also say it is a required field.

As we init the option properties in createOptions, localGitRepo and patchBranch is required, checkstyleTesterPath and stopAfterGenerateConfig is not.
If localGitRepo is missing, then program would stop at

        try {
            cmd = parser.parse(options, args);
        }
        catch (ParseException ex) {
            System.err.println(ex.getMessage());
            formatter.printHelp(null, options);
            System.exit(1);
        }

as there would be a ParseException, with message like Missing required option XX.
Meanwhile, immutable class would validate fields not null when it is being created. So repoPath is impossible to be null in validateArguments method.

But checkstyleTesterPath is not required, so we use Optional field in Arguments. And a NoSuchElementException would be thrown if we try to do checkstyleTesterPath().get() when it is null.
I have updated validateArguments to throw a clearer message for this case.

Copy link
Member

@rnveach rnveach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't see anything else.
Please add to issue what was done and what was left when this is merged. Don't forget we need full documentation in the readme.

/**
* Runs the regression tool.
* @param args the parsed CLI arguments.
* @throws Exception excute failure
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

excute => execute

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. My typo check was accidentally disabled before. :-(

* @return the generated config file
* @throws Exception generation failure
*/
private static File generateConfig(String repoPath, String branch)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even though we don't need the entire arguments class, I sorta like sending it better than its pieces. Less documentation and easier to grab new arguments that we add.
What do you think about this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My mistake. I forgot to update this one.
This is done.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 24, 2017

@rnveach

Please add to issue what was done and what was left when this is merged. Don't forget we need full documentation in the readme.

I am facing an error Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes, when trying java -jar .. to run the jar file. I have searched about this for a while but failed to solve it. So by now I haven't really use CLI to see how it works now.

Docs in other issue?

@rnveach
Copy link
Member

rnveach commented Jul 25, 2017

Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes

I will look into. Please add JAR generation to travis and appveyor.

Docs in other issue?

If you mean adding documentation, it can be in the issue this PR references.

@rnveach
Copy link
Member

rnveach commented Jul 25, 2017

@Luolc
Copy link
Contributor Author

Luolc commented Jul 25, 2017

@rnveach

Try adding this: https://github.com/checkstyle/checkstyle/blob/master/pom.xml#L927-L947
Still having error. pom update is pushed.

My command:

$ mvn clean package -Passembly
$ java -jar target/regression-tool-1.0-SNAPSHOT-all.jar -r path/to/checkstyle -b branch --stopAfterGenerateConfig
Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes
	at sun.security.util.SignatureFileVerifier.processImpl(SignatureFileVerifier.java:314)
	at sun.security.util.SignatureFileVerifier.process(SignatureFileVerifier.java:268)
	at java.util.jar.JarVerifier.processEntry(JarVerifier.java:316)
	at java.util.jar.JarVerifier.update(JarVerifier.java:228)
	at java.util.jar.JarFile.initializeVerifier(JarFile.java:383)
	at java.util.jar.JarFile.getInputStream(JarFile.java:450)
	at sun.misc.URLClassPath$JarLoader$2.getInputStream(URLClassPath.java:940)
	at sun.misc.Resource.cachedInputStream(Resource.java:77)
	at sun.misc.Resource.getByteBuffer(Resource.java:160)
	at java.net.URLClassLoader.defineClass(URLClassLoader.java:454)
	at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
	at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
	at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
	at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
	at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

Please add JAR generation to travis and appveyor.

Do you mean adding a mvn clean package -Passembly in travis and appveyor?

@rnveach
Copy link
Member

rnveach commented Jul 25, 2017

Do you mean adding a mvn clean package -Passembly in travis and appveyor?

Yes.
I got a different error when packaging, I will try again soon.

@rnveach
Copy link
Member

rnveach commented Jul 25, 2017

@Luolc see http://zhentao-li.blogspot.com/2012/06/maven-shade-plugin-invalid-signature.html . It is the first result that comes up in google and it fixed the issue for me.

}
catch (ParseException ex) {
System.err.println(ex.getMessage());
formatter.printHelp(null, options);
Copy link
Member

@rnveach rnveach Jul 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This produces the following exception when called with no arguments:

java.lang.IllegalArgumentException: cmdLineSyntax not provided

This is not helpful to users at all.

Copy link
Contributor Author

@Luolc Luolc Jul 26, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. cmdLineSyntax is not allowed to be null or empty. Now I pass a "regression-tool" to it. (the argument is shown after usage:)
Acts like:

$ java -jar target/regression-tool-1.0-SNAPSHOT-all.jar
Missing required options: r, p
usage: regression-tool
 -p,--patchBranch <arg>            the name of the PR branch
 -r,--localGitRepo <arg>           the path of the checkstyle repository
    --stopAfterGenerateConfig      indicates that regression tool would
                                   stop after generating config
 -t,--checkstyleTesterPath <arg>   the path of the checkstyle-tester
                                   directory

@Luolc Luolc force-pushed the issue32 branch 2 times, most recently from 595c74c to c4ea1a4 Compare July 26, 2017 17:16
@Luolc
Copy link
Contributor Author

Luolc commented Jul 26, 2017

Please add JAR generation to travis and appveyor.

Done.

see http://zhentao-li.blogspot.com/2012/06/maven-shade-plugin-invalid-signature.html . It is the first result that comes up in google and it fixed the issue for me.

It works, thanks. I found similar answer at StackOverflow before but it seems missed line <artifact>*:*</artifact>.

@rnveach
Copy link
Member

rnveach commented Jul 26, 2017

usage: regression-tool

It should be java -jar regression-tool.jar (not sure about version number) and shouldn't it include some text describing the optional arguments like other programs do?
Example from java:

Usage: java [-options] class [args...]
          (to execute a class)
  or  java [-options] -jar jarfile [args...]
          (to execute a jar file)

@Luolc
Copy link
Contributor Author

Luolc commented Jul 27, 2017

@rnveach
I wrote regression-tool for I read its source code and found the parameter of its internal method is named as appName, while I don't actually know why.

Edit: I find the proper way in javadoc of class HelpFormatter.

formatter.printHelp("myapp", header, options, footer, true);

Sample output:

usage: myapp -f <FILE> [-h] [-v]

Now I understand the meaning of the first parameter. It supposed we are running command like mvn ..., git ... etc. And the last parameter true is turning on autoUsage mode.

Now our code:

formatter.printHelp("java -jar regression-tool.jar", options, true);

Output:

$ java -jar target/regression-tool-1.0-SNAPSHOT-all.jar
Missing required options: r, p
usage: java -jar regression-tool.jar -p <arg> -r <arg>
       [--stopAfterGenerateConfig] [-t <arg>]
 -p,--patchBranch <arg>            the name of the PR branch
 -r,--localGitRepo <arg>           the path of the checkstyle repository
    --stopAfterGenerateConfig      indicates that regression tool would
                                   stop after generating config
 -t,--checkstyleTesterPath <arg>   the path of the checkstyle-tester
                                   directory

One problem is the version number. Should we specify it manually every time we update, or trying to detect the version number from maven settings?

@rnveach
Copy link
Member

rnveach commented Jul 27, 2017

@Luolc lets leave version number to another time. It will have to detect snapshot too. There should be some way for maven to inject the needed data for us to acquire at runtime.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 27, 2017

@rnveach OK.
Is there anything else need to improve in this PR?

}
catch (ParseException ex) {
System.err.println(ex.getMessage());
formatter.printHelp("regression-tool", options);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

waiting for this update...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I found I didn't successfully push the changes before. Updated.

Copy link
Member

@rnveach rnveach left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about this comment at #57 (comment) ?
Edit: fixed link.

Once these 2 are done, I will merge this.

}
else {
throw new IllegalArgumentException("missing checkstyleTesterPath, "
+ "which is required if you are using --stopAfterGenerateConfig mode");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't this be if you are not using --stopAfterGenerateConfig mode?
The if statement above is if (!args.stopAfterGenerateConfig()).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 27, 2017

@rnveach

What about this comment at https://github.com/checkstyle/regression-tool/pull/57/files/6a2f57678ca9ae6ab78bb5cd7b5669200be3f45e#discussion_r128928723 ?

I got a We went looking everywhere, but couldn’t find those commits. page.

@rnveach
Copy link
Member

rnveach commented Jul 27, 2017

@Luolc I edited the comment after I noticed it, please re-check the new link.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 27, 2017

@rnveach
I mentioned this at #57 (comment)

The explanation in detail is at that post.
If repo path is not given, the program would stop earlier and at that line repo is not possible to be null.

@rnveach
Copy link
Member

rnveach commented Jul 27, 2017

ok, I missed that since it was separate. Once CI is done I will merge.

@Luolc
Copy link
Contributor Author

Luolc commented Jul 27, 2017

#59 This issue for creating a document of this tool.

@rnveach rnveach merged commit bb25bd3 into checkstyle:master Jul 27, 2017
@Luolc Luolc deleted the issue32 branch July 27, 2017 15:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants