jabref icon indicating copy to clipboard operation
jabref copied to clipboard

Fixes #13274: Allow cygwin-paths on Windows

Open kvitorr opened this issue 6 months ago • 15 comments

Closes https://github.com/JabRef/jabref/issues/13274

Allow cygwin-paths on Windows

Create the method convertCygwinPathToWindows in the FileUtil class. It transforms a file path from Cygwin-style to Windows-style only if the operating system is Windows.

Based on research, the two common Cygwin-style formats are:

  • /cygdrive/{drive}/some/path
  • /{drive}/some/path

The third was asked to be added

  • /mnt/{drive}/Users/ (asked in the code review)

The method follows this logic:

/// Converts a Cygwin-style file path to a Windows-style path if the operating system is Windows.
    ///
    /// Supported formats:
    /// - /cygdrive/c/Users/... → C:\Users\...
    /// - /mnt/c/Users/...      → C:\Users\...
    /// - /c/Users/...          → C:\Users\...
    ///
    /// @param filePath the input file path
    /// @return the converted path if running on Windows and path is in Cygwin format; otherwise, returns the original path
    public static Path convertCygwinPathToWindows(String filePath) {
        if (filePath == null) {
            return null;
        }

        if (!OS.WINDOWS) {
            return Path.of(filePath);
        }

        if (filePath.startsWith(MNT_PREFIX) && filePath.length() > 5) {
            return buildWindowsPathWithDriveLetterIndex(filePath, 5);
        }

        if (filePath.startsWith(CYGDRIVE_PREFIX) && filePath.length() > 10) {
            return buildWindowsPathWithDriveLetterIndex(filePath, 10);
        }

        if (ROOT_DRIVE_PATTERN.matcher(filePath).matches()) {
            return buildWindowsPathWithDriveLetterIndex(filePath, 1);
        }

        return Path.of(filePath);
    }

    /// Builds a Windows-style path from a Cygwin-style path using a known prefix index.
    /// @param path the input file path
    /// @param letterIndex the index driver letter, zero-based indexing
    /// @return a windows-style path
    private static Path buildWindowsPathWithDriveLetterIndex(String path, int letterIndex) {
        String driveLetter = path.substring(letterIndex, letterIndex + 1).toUpperCase();
        String windowsPath = path.substring(letterIndex + 1).replace("/", "\\\\");
        return Path.of(driveLetter + ":" + windowsPath);
    }

Additionally, unit tests for this method were added to FileUtilTest class

OBS: I need help to run the second test when Windows is disabled... I am getting an error because the test is not recognized...

    @DisabledOnOs(value = org.junit.jupiter.api.condition.OS.WINDOWS, disabledReason = "Test in others operational systems")
    @ParameterizedTest
    @ValueSource(strings = {"/home/username/Downloads/test.bib"})
    void convertCygwinPathToWindowsShouldReturnOriginalFilePathWhenRunningOnWindows(String filePath) {
        assertEquals(Path.of(filePath), FileUtil.convertCygwinPathToWindows(filePath));
    }

It was created a Converter, called CygwinPathConverter, as requested on the code review... and it was added to the Option Anottation in the classes: CheckConsistency.java, CheckIntegrity.java, Convert.java, Pseudonymize.java, Search.java

Example of use:

@Option(names = {"--input"}, converter = CygWinPathConverter.class, description = "Input BibTeX file", required = true)
    private Path inputFile;

Mandatory checks

  • [x] I own the copyright of the code submitted and I license it under the MIT license
  • [x] Change in CHANGELOG.md described in a way that is understandable for the average user (if change is visible to the user)
  • [x] Tests created for changes (if applicable)
  • [ ] Manually tested changed features in running JabRef (always required)
  • [/] Screenshots added in PR description (if change is visible to the user)
  • [x] Checked developer's documentation: Is the information available and up to date? If not, I outlined it in this pull request.
  • [ ] Checked documentation: Is the information available and up to date? If not, I created an issue at https://github.com/JabRef/user-documentation/issues or, even better, I submitted a pull request to the documentation repository.

kvitorr avatar Jun 10 '25 01:06 kvitorr

Please add a CHANGELOG.md entry 😅

koppor avatar Jun 10 '25 14:06 koppor

Tests look good!

Now, weave it in into JabKit

koppor avatar Jun 10 '25 14:06 koppor

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

kvitorr avatar Jun 10 '25 16:06 kvitorr

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

No need to create tests there. Just implement the transformation of the --input (and --output) filename(s).

koppor avatar Jun 10 '25 21:06 koppor

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

No need to create tests there. Just implement the transformation of the --input (and --output) filename(s).

already done that in the last commit

kvitorr avatar Jun 10 '25 22:06 kvitorr

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

No need to create tests there. Just implement the transformation of the --input (and --output) filename(s).

already done that in the last commit

See my comment. Is it possible to move the logic towards the --import argument?

Reason: should also work at pseudonymization and check consistency, not only import. (If I understand the current diff right currently only at the import command it's working. Did you try out for pseudonymize?)

koppor avatar Jun 11 '25 03:06 koppor

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

No need to create tests there. Just implement the transformation of the --input (and --output) filename(s).

already done that in the last commit

See my comment. Is it possible to move the logic towards the --import argument?

Reason: should also work at pseudonymization and check consistency, not only import. (If I understand the current diff right currently only at the import command it's working. Did you try out for pseudonymize?)

sorry... I didn't see your comment. I'll try to understand what are you saying and then I'll comeback with some commit or comment

kvitorr avatar Jun 11 '25 03:06 kvitorr

@koppor, can you help me? I’m not sure where to create the test for the ArgumentProcessor class. Also, would you like me to rename the test cases?

No need to create tests there. Just implement the transformation of the --input (and --output) filename(s).

already done that in the last commit

See my comment. Is it possible to move the logic towards the --import argument?

Reason: should also work at pseudonymization and check consistency, not only import. (If I understand the current diff right currently only at the import command it's working. Did you try out for pseudonymize?)

sorry... I didn't see your comment. I'll try to understand what are you saying and then I'll comeback with some commit or comment

Maybe it got lost while I was on the road.

There is a place in the code where --input is mapped to a Java object variable by the picocli annotation @option (or similar). Maybe, there is a transformion possible.

koppor avatar Jun 11 '25 04:06 koppor

Please put in your classname sthg about Cygwin Path, because picocli does nativly support Path as a filetype ( https://picocli.info/quick-guide.html#_type_conversion ) and nobody gets the impression that this is some unneccessary conversion class.

calixtus avatar Jun 13 '25 12:06 calixtus

You have to do your changes (add line, remove line) manually. GitHub does not yet support nativly commands in the comment section to modify your code.

Please always remember: https://github.com/JabRef/jabref/blob/main/CONTRIBUTING.md#notes-on-ai-usage

calixtus avatar Jun 13 '25 12:06 calixtus

@calixtus thank you for your time, I will do the changes and then wait for the feedback. Please be patient xD, I am doing my best.

kvitorr avatar Jun 13 '25 13:06 kvitorr

@koppor @calixtus

I made new changes to the project...

  • I changed the type of the --input and --output attributes from String and File to Path as requested.

  • I removed the code duplication from the converters and changed the name of PathConverter to CygwinPathConverter so that no one gets the impression that it is an unnecessary conversion class, as pointed out by calixtus.

  • I changed the ConvertCygwinPathToWindows method of the FileUtil class to return a Path instead of a String.

  • I created three constants in the FileUtil class, two representing the prefixes "/mnt/" and "/cygdrive/"... the third constant represents the pattern /{driveLetter}/... which are being used within the conditionals.

  • I created a private method within the FileUtil class that is being used within ConvertCygwinPathToWindows... this code snippet was being repeated within the conditionals... and since code duplication was something that was mentioned in the review, I thought it would be better to create this new method.

Other than that, I didn't manually test the changes but I wanted to upload the modification right away so you could give me feedback on whether I understood the requested changes correctly.

I also updated the pull request description.


Regarding the use of AI, I understand your point of view, but I didn't find your comments interesting.

I use it to understand the code, understand dependencies, understand business rules, make comparisons between technologies, understand differences between data types, and try to bring more context to some of the comments you make.

The pull request description was not made using AI, and I understood the changes that were made and also tested it locally.

Yes, there was code duplication, but I didn't understand whether the data type received by the CLI could be changed from String/File to Path. My thought at the time was "if the code is using different data types for input and output, there must be a reason." And that's why I created the three converters, String, File, and Path.

So I thought, I'll upload the change and wait for the review. If I need to change something, it will be requested.

Since this is my FIRST open source contribution, I expected it to be a cool experience. In fact, I'm learning a lot, having contact with organized code, with tests, with documentation and with Picocli, but these comments about the use of AI caught me by surprise.

I read Daniel Roe's text (https://roe.dev/blog/using-ai-in-open-source) and I feel like I didn't deviate from anything he said.

But since this was pointed out to me, I also want to point out something to you, that you at least read the entire description of the pull request and answer any questions written there... this will help clarify ideas, allow a better understanding of the issue and maintain a good environment for both of us.

And, as it is said in the contribution guide, you can reject the PR if you think it doesn't contribute anything to this issue.

kvitorr avatar Jun 14 '25 01:06 kvitorr

Sorry you got offended by our comment about ai. It's partially a precaution since we get a lot of contributions lately that are completely ai generated, look nice on first sight, but are rubbish on second.

We are not against use of ai, in fact we use it ourselves for repeating task, for simple refactors etc. The general rule is: never to use generated stuff without reading it, testing it and owning it. In short: Never let an ai think for you. Never let an ai speak for you.

There were some indicators, that some of your changes were generated. Maybe it is also our perspective, that makes look changes a newcomer made without much experience so partially similar to changes a LLM does. Eg. Your comments remove line and add line looked like commands one wanted to send to an ai.

Please don't be alienated by our precautions. We're always happy about newcomers and try to be welcoming. This is why we did comment on your changes and not just close the pr without comment because we would have thought that this would just be another ai pr.

calixtus avatar Jun 14 '25 07:06 calixtus

Looks good to me so far... is this still a draft or ready for review?

calixtus avatar Jun 14 '25 16:06 calixtus

@kvitorr Do you intend to continue working on this? I think, it is "just" about addressing my small comments, fix jbang and merge main branch.

koppor avatar Jul 04 '25 06:07 koppor

@kvitorr Will you continue here?

koppor avatar Jul 28 '25 21:07 koppor

Hi @kvitorr i tried to merge current main into your PR and finish it, but you have your branch protected against maintainer pushes. Please either finish the PR yourself or allow maintainer pushes (checkbox in the pr visible to you) so we can finish it. Otherwise we would have to close this PR, which would be a real shame, as the code looks good (except small remarks by koppor) and the addition is really good.

calixtus avatar Aug 22 '25 16:08 calixtus

Hi @kvitorr i tried to merge current main into your PR and finish it, but you have your branch protected against maintainer pushes. Please either finish the PR yourself or allow maintainer pushes (checkbox in the pr visible to you) so we can finish it. Otherwise we would have to close this PR, which would be a real shame, as the code looks good (except small remarks by koppor) and the addition is really good.

sorry, I was not accessing the email that is connected to my github and did not see the comments on the PR. I'll will make the changes requested.

kvitorr avatar Aug 22 '25 21:08 kvitorr

Note that your PR will not be reviewed/accepted until you have gone through the mandatory checks in the description and marked each of them them exactly in the format of [x] (done), [ ] (not done yet) or [/] (not applicable).

jabref-machine avatar Sep 03 '25 21:09 jabref-machine

@trag-bot didn't find any issues in the code! ✅✨

trag-bot[bot] avatar Sep 03 '25 21:09 trag-bot[bot]