Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

mharbison72
Copy link
Contributor

@mharbison72 mharbison72 commented Feb 9, 2025

Proposed changes

The first commit causes the typical system and user level Mercurial config files to be read when running commands through JavaHg (which seems to be everything except clients pushing to or pulling from the server). Reading global config was already the case for client push and pull operations. This is important because those config files may cause extensions to load, and some extensions are required to operate on the repository in any manner. For example, I found this issue when trying to import LFS repositories when upgrading from 1.58.

The second commit ensures that every command has its own copy of the configuration instead of a shared config object, because each command has the opportunity to modify the configuration object. There's a bit of detail in the commit message.

The third commit is a simplification of how temporary config options are taken from the UI, and injected into the process (e.g. the username and password on repo import). Because it's simpler to add another config file to the command instead of modifying (a possibly) existing one, some of the tests can go away. The remaining tests cover the format and lifespan of this additional (temporary) config file.

I see this talks about squashing the commits and using this text as the commit message, so if you'd like separate PRs, I can do that. The commit messages describe what's going on better, and the 3rd commit has a lot of code churn that I didn't see a way to break up. But I thought these were related enough to send in one group.

Your checklist for this pull request

Contributor:

  • PR is well described and the description can be used as a commit message on squash
  • Related issues linked to PR if existing and labels set
  • New code is covered with unit tests
  • Changelog entry file created in gradle/changelog

Reviewer:

  • The clean code principles are respected (CleanCode)
  • All new code/logic is implemented on the right spot / "Should this be done here?"

Checklist for branch merge request (not required for forks)

There was previously a weird duality where a simple push to or pull from a
repository hosted by SCM-Manager would load all of the system and user level
config files, but they were ignored when importing a repository.  I found this
out when importing an LFS repo, and it eventually failed with a message that the
LFS extension needs to be enabled, even though it was enabled globally.  The
global config should typically never be ignored, because some repositories are
unreadable without certain extensions or configurations.

The JavaHg API here mirrors the hg behavior for the `HGRCPATH` environment
variable- not setting it (or null here) uses the default config resolution, and
`""` (the default in JavaHg for some reason) disables default config resolution.
The repository initialization code in JavaHg also uses `""`, and there's no way
to alter that from the outside.  But that appears to be harmless, so I'm
ignoring that for now.  Note that this may only have been a problem on
non-Windows systems- setting an environment variable to empty on Windows
*unsets* the variable, even in the `_wputenv()` API, which is what we want.

After this, normal push/pull operations continue to use the global config.  But
now imports from the SCM-Manager UI, the hooks run during a push, and any other
commands that are run through JavaHg will see a consistent configuration.  LFS
(and maybe largefiles- I haven't tested it) repository imports now work.  (I
wouldn't say "supported" yet because it doesn't pull the blobs.  The largefiles
extension has a command for doing this, but the LFS extension doesn't.  The
stopgap for this is to run `hg verify` to download the blobs, but that won't
work here with the way subrepos aren't nested as expected.  I can work on a
command on the hg side to fill this gap.)

One final thing to note here- as I was testing, I initially got authentication
failures when trying to pull.  It happened several times as I added more and
more logging, then disappeared, and I wasn't able to trigger it again as I
backed off the logging to get to this change alone.  The auth info is written to
the repository's hgrc file, so a change to whether or not the global
configuration is processed is irrelevant.  The next couple of commits will try
to improve the related code.
…singleton

I can't point to a specific error, but modifying a singleton and reusing it is
a good way to get unexpected state.  The extension adding won't collect
additional state (it's add-if-not-present), but the underlying
`java.util.HashMap` isn't threadsafe.  Any differences in the environment map
when this is called would alter that state of anything else that still held a
configuration (and it also uses `HashMap`), and the pending changeset, encoding,
and HgBin settings would be overwritten for everybody outright.

There's only a default constructor for this class, so nothing to pass along in
the constructor.  I don't *think* this was the cause of the random auth failures
mentioned in the previous commit, but it's easy to avoid these potential
problems.
…tions

Modifying the config file is complicated and error prone, but there hasn't been
any other option aside from setting `HGRCPATH` to point to a standalone file.
Starting with Mercurial 7.0 (scheduled for March 2025), there's now a global
option to specify one or more additional config files on the command line,
without disabling the normal system and user level config file processing.[1]
Since I'm not sure what the minimum supported Mercurial is for this project,
this includes an extension that backports the same option if it is not present
in the version of Mercurial that is used, and does nothing if Mercurial natively
supports it.  I tested back to Mercurial 6.0, which should be more than
sufficient- 6.1.4 (June 2022) was the last release to support Python 2 (which
has been EOL since Jan 2020), and the Python 3 support before that release was
considered experimental.  It likely works in earlier versions, but there's a
definite minimum of 4.9 (Feb 2019), due to the `exthelper` module import.

Without the need to modify a possibly existing file and then restore it when
done, a bunch of code falls away, and the tests that supported it.


[1] https://repo.mercurial-scm.org/hg/rev/25b344f2aeef
@CLAassistant
Copy link

CLAassistant commented Feb 9, 2025

CLA assistant check
All committers have signed the CLA.

@mharbison72
Copy link
Contributor Author

If what I did in the 3rd commit (provide a Mercurial extension to backfill for versions that don't have specific functionality) is OK, I can probably do something similar to pull the LFS blobs to the server when importing, and then I think you can claim support for LFS with Mercurial. We've been using LFS with a slightly tweaked 1.58 build, and the only issue I ran into was this config file stuff when importing.

@pfeuffer
Copy link
Member

Thanks a lot for your submission, @mharbison72 ! We will take a look at it in the next days.

Copy link
Member

@fscholdei fscholdei left a comment

Choose a reason for hiding this comment

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

That looks good to me. Thanks again for the contribution. Would you like to take another look, @pfeuffer?
In this case, I think it makes sense not to squash the PR.

@fscholdei fscholdei added the bug Something isn't working label Feb 25, 2025
@pfeuffer
Copy link
Member

Hi @mharbison72 ,

our internal Jenkins shows failing tests on your branch. Interestingly, one is TemporaryConfigFactoryTest.shouldNotCreateHgrc():

image

The other two tests are from our SimpleHgWorkingCopyFactoryTest:

image

Do these tests run on your maching? May this have something to do with the hg version?

@mharbison72
Copy link
Contributor Author

@pfeuffer - I think they're running, but this is definitely strange. It took be a bit, but IIUC, the first one is complaining because a null is being passed to assertThat(). That's what the code does on purpose, so I think I need to fix that. (IDK why neither my tests nor the ones run here on GH see that issue though. LMK if/when I should push a change, in case you want to investigate this more.)

The second 2 failures might be hg version dependent, though I'm not entirely sure what they are trying to test for. It looks like it wants to test manipulating the working directory, but I'm not sure why that would ever be done on a server through a hosting provider. (What are you running?- I've been running 6.9.1 locally, but I don't see why my change would affect these tests at all.)

In any case, I'm happy to poke at the tests too (if I can reproduce the problem locally). I added the transcript of the test run in case I'm doing something wrong. There are a few failures in DAO tests, but those existed without my changes.

C:\Users\Matt\projects\scm-manager\scm-manager>gradlew clean war test
Starting a Gradle Daemon (subsequent builds will be faster)
Using Jakarta EE dependencies for scm-git-plugin
Using Jakarta EE dependencies for scm-hg-plugin
Using Jakarta EE dependencies for scm-legacy-plugin
Using Jakarta EE dependencies for scm-svn-plugin

> Task :scm-ui:yarn_install
yarn install v1.22.22
[1/4] Resolving packages...
warning Resolution field "@types/[email protected]" is incompatible with requested version "@types/react@^16"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
success Already up-to-date.
Done in 0.87s.

> Task :scm-plugins:scm-git-plugin:yarn_install
yarn install v1.22.15
[1/4] Resolving packages...
warning Resolution field "@types/[email protected]" is incompatible with requested version "@types/react@^16"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
success Already up-to-date.
Done in 0.52s.

> Task :scm-plugins:scm-git-plugin:ui-bundle
yarn run v1.22.15
$ plugin-scripts build
C:\Users\Matt\projects\scm-manager\scm-manager\scm-plugins\scm-git-plugin\node_modules\@scm-manager\ui-plugins\package.json
asset scm-git-plugin.bundle.js 76.9 KiB [emitted] [minimized] (name: scm-git-plugin)
orphan modules 26 KiB [orphan] 12 modules
runtime modules 964 bytes 5 modules
built modules 29.3 KiB [built]
  modules by path external "@scm-manager/ 210 bytes
    external "@scm-manager/ui-extensions" 42 bytes [built] [code generated]
    external "@scm-manager/ui-components" 42 bytes [built] [code generated]
    + 3 modules
  cacheable modules 28.8 KiB
    ../../node_modules/@scm-manager/plugin-scripts/src/webpack-public-path.js 932 bytes [built] [code generated]
    ./src/main/js/index.ts + 12 modules 27.9 KiB [built] [code generated]
  external "react" 42 bytes [built] [code generated]
  external "classnames" 42 bytes [built] [code generated]
  external "styled-components" 42 bytes [built] [code generated]
  external "react-i18next" 42 bytes [built] [code generated]
  external "react-hook-form" 42 bytes [built] [code generated]
webpack 5.94.0 compiled successfully in 16672 ms
Done in 24.71s.

> Task :scm-plugins:scm-hg-plugin:compileJava
warning: Supported source version 'RELEASE_8' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '17'
warning: Supported source version 'RELEASE_8' from annotation processor 'org.gradle.api.internal.tasks.compile.processing.TimeTrackingProcessor' less than -source '17'
C:\Users\Matt\projects\scm-manager\scm-manager\scm-plugins\scm-hg-plugin\src\main\java\sonia\scm\api\v2\resources\HgGlobalConfigToHgGlobalConfigDtoMapper.java:35: warning: Unmapped target property: "allowDisable". Occured at 'D map(T arg0)' in 'BaseMapper'.
public abstract class HgGlobalConfigToHgGlobalConfigDtoMapper extends BaseMapper<HgGlobalConfig, HgGlobalGlobalConfigDto> {
                ^
Note: Some input files use or override a deprecated API.
Note: Recompile with -Xlint:deprecation for details.
3 warnings

> Task :scm-plugins:scm-hg-plugin:openapi
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.

> Task :scm-plugins:scm-hg-plugin:yarn_install
yarn install v1.22.15
[1/4] Resolving packages...
warning Resolution field "@types/[email protected]" is incompatible with requested version "@types/react@^16"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
success Already up-to-date.
Done in 0.56s.

> Task :scm-plugins:scm-hg-plugin:ui-bundle
yarn run v1.22.15
$ plugin-scripts build
C:\Users\Matt\projects\scm-manager\scm-manager\scm-plugins\scm-hg-plugin\node_modules\@scm-manager\ui-plugins\package.json
asset scm-hg-plugin.bundle.js 62.2 KiB [emitted] [minimized] (name: scm-hg-plugin)
orphan modules 20.8 KiB [orphan] 11 modules
runtime modules 690 bytes 4 modules
built modules 23.8 KiB [built]
  modules by path external "@scm-manager/ 168 bytes
    external "@scm-manager/ui-extensions" 42 bytes [built] [code generated]
    external "@scm-manager/ui-components" 42 bytes [built] [code generated]
    external "@scm-manager/ui-api" 42 bytes [built] [code generated]
    external "@scm-manager/ui-core" 42 bytes [built] [code generated]
  cacheable modules 23.5 KiB
    ../../node_modules/@scm-manager/plugin-scripts/src/webpack-public-path.js 932 bytes [built] [code generated]
    ./src/main/js/index.ts + 11 modules 22.6 KiB [built] [code generated]
  external "react" 42 bytes [built] [code generated]
  external "react-i18next" 42 bytes [built] [code generated]
webpack 5.94.0 compiled successfully in 1613 ms
Done in 2.70s.

> Task :scm-plugins:scm-legacy-plugin:yarn_install
yarn install v1.22.15
[1/4] Resolving packages...
warning Resolution field "@types/[email protected]" is incompatible with requested version "@types/react@^16"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
success Already up-to-date.
Done in 0.54s.

> Task :scm-plugins:scm-legacy-plugin:ui-bundle
yarn run v1.22.15
$ plugin-scripts build
C:\Users\Matt\projects\scm-manager\scm-manager\scm-plugins\scm-legacy-plugin\node_modules\@scm-manager\ui-plugins\package.json
asset scm-legacy-plugin.bundle.js 16.7 KiB [emitted] [minimized] (name: scm-legacy-plugin)
runtime modules 690 bytes 4 modules
orphan modules 1.64 KiB [orphan] 3 modules
built modules 5.85 KiB [built]
  cacheable modules 5.69 KiB
    ../../node_modules/@scm-manager/plugin-scripts/src/webpack-public-path.js 932 bytes [built] [code generated]
    ./src/main/js/index.tsx + 3 modules 4.78 KiB [built] [code generated]
  modules by path external "@scm-manager/ 84 bytes
    external "@scm-manager/ui-extensions" 42 bytes [built] [code generated]
    external "@scm-manager/ui-components" 42 bytes [built] [code generated]
  external "react" 42 bytes [built] [code generated]
  external "react-router-dom" 42 bytes [built] [code generated]
webpack 5.94.0 compiled successfully in 1379 ms
Done in 2.52s.

> Task :scm-plugins:scm-svn-plugin:yarn_install
yarn install v1.22.15
[1/4] Resolving packages...
warning Resolution field "@types/[email protected]" is incompatible with requested version "@types/react@^16"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
warning Resolution field "[email protected]" is incompatible with requested version "react@^16.8.3"
success Already up-to-date.
Done in 0.54s.

> Task :scm-plugins:scm-svn-plugin:ui-bundle
yarn run v1.22.15
$ plugin-scripts build
C:\Users\Matt\projects\scm-manager\scm-manager\scm-plugins\scm-svn-plugin\node_modules\@scm-manager\ui-plugins\package.json
asset scm-svn-plugin.bundle.js 29.7 KiB [emitted] [minimized] (name: scm-svn-plugin)
orphan modules 8.38 KiB [orphan] 7 modules
runtime modules 690 bytes 4 modules
built modules 10.8 KiB [built]
  modules by path external "@scm-manager/ 126 bytes
    external "@scm-manager/ui-extensions" 42 bytes [built] [code generated]
    external "@scm-manager/ui-components" 42 bytes [built] [code generated]
    external "@scm-manager/ui-core" 42 bytes [built] [code generated]
  cacheable modules 10.6 KiB
    ../../node_modules/@scm-manager/plugin-scripts/src/webpack-public-path.js 932 bytes [built] [code generated]
    ./src/main/js/index.ts + 7 modules 9.69 KiB [built] [code generated]
  external "react" 42 bytes [built] [code generated]
  external "react-i18next" 42 bytes [built] [code generated]
webpack 5.94.0 compiled successfully in 1418 ms
Done in 2.53s.

> Task :scm-webapp:war
Encountered duplicate path "WEB-INF/plugins/README" during copy operation configured with DuplicatesStrategy.WARN

> Task :scm-dao-xml:test
OpenJDK 64-Bit Server VM warning: Sharing is only supported for boot loader classes because bootstrap classpath has been appended

PathBasedRepositoryLocationResolverTest > WithExistingData > shouldHandleErrorOnModifyLocation() FAILED
    java.lang.UnsupportedOperationException at PathBasedRepositoryLocationResolverTest.java:228

DataFileCacheTest > WithActivatedCache > shouldRemoveOutdatedDataIfOfDifferentType() FAILED
    org.opentest4j.AssertionFailedError at DataFileCacheTest.java:90

DataFileCacheTest > WithActivatedCache > shouldReadDataAnewIfOfDifferentType() FAILED
    java.lang.AssertionError at DataFileCacheTest.java:77

DataFileCacheTest > WithActivatedCache > shouldReadDataIfNotCached() FAILED
    java.lang.AssertionError at DataFileCacheTest.java:64

DataFileCacheTest > WithActivatedCache > shouldReturnCachedData() FAILED
    java.lang.RuntimeException at DataFileCacheTest.java:49

126 tests completed, 5 failed

> Task :scm-dao-xml:test FAILED

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':scm-dao-xml:test'.
> There were failing tests. See the report at: file:///C:/Users/Matt/projects/scm-manager/scm-manager/scm-dao-xml/build/reports/tests/test/index.html

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.6.4/userguide/command_line_interface.html#sec:command_line_warnings

BUILD FAILED in 4m 14s
85 actionable tasks: 46 executed, 20 from cache, 19 up-to-date

@mharbison72
Copy link
Contributor Author

@pfeuffer gentle ping on this. I need clarification on how to run the tests (i.e. why they pass for me, even though at least one of the tests looks like it is properly failing for you).

@pfeuffer
Copy link
Member

@mharbison72 , sorry for the late reply. I'm not sure why you have a failing test in the dao-xml module. But you should be able to run the hg tests alone with

gradlew :scm-plugins:scm-hg-plugin:test

Does this work for you?

@mharbison72
Copy link
Contributor Author

@mharbison72 , sorry for the late reply. I'm not sure why you have a failing test in the dao-xml module. But you should be able to run the hg tests alone with

gradlew :scm-plugins:scm-hg-plugin:test

Does this work for you?

@pfeuffer- sorta. I now see the TemporaryConfigFactoryTest failure that's caused by a NPE and fixed that, but I'm getting 231 tests completed, 32 failed, and 2 skipped. I get 5 failures in SimpleHgWorkingCopyFactoryTest alone (you listed only 2). If I run the tests on the parent of my PR, I get 234 tests completed, 31 failed, 2 skipped, and there seems to be one less SimpleHgWorkingCopyFactoryTest failure. The one common failure we have prior to the PR that you mention is shouldDeleteUntrackedDirectory, but that seems like something hg itself should manage.

I guess my first question is, do you run these tests in Jenkins on Windows, or just Linux/something else? It seems like there's a lot of pre-existing broken stuff, but I can't tell offhand if they are tests not written with Windows in mind, or if it's something else. I can run in WSL if needed, but I let IntelliJ grab the JDKs and dependencies in Windows, and I'd have to figure all of that out on my own in WSL. Also, I'm not sure if the code being tested is actually used by SCM Manager. I'm not sure why SCM Manager would be trying to create tags or branches, or why it would do hg outgoing commands, for example. (HgBranchCommandTest, HgModifyCommandTest, HgOutgoingCommandTest, and HgTagCommandTest are the other failures I'm seeing now, prior to the PR.)

I'll see if I can hack around in SimpleHgWorkingCopyFactoryTest to figure out what is going on there.

@pfeuffer
Copy link
Member

Thanks for your effort, @mharbison72 ! You've guessed right, our Jenkins only runs the build under Linux, and most of our devs also use Linux. To be honest, I'm struggling with hg myself at the moment. On my local machine, I also get test errors and I'm not sure, why. In our Jenkins, they are running smooth. Maybe this is related to the versions of Mercurial itself or Python. I'll try to take a look at this and get back to you.

@mharbison72
Copy link
Contributor Author

@pfeuffer What version of Mercurial do you have on Jenkins? We put binary wheels on PyPI now, so I can walk you through setting up a local venv and installing in there on your Jenkins system, so you don't have to mess with whatever you have installed globally on Jenkins. (Python 3.8 will be the minimum for 6.9.x. Python 3.6 and 3.7 support was dropped not that long ago, so that's a possibility too if that system is older.)

I also just rebased and pushed the fix for the first failure in TemporaryConfigFactoryTest.shouldNotCreateHgrc(), because that was actually wrong. I didn't rebase the 2 commits stacked on top that fixed the license and changelog, because they look like they're on a different branch (github/2247), and I'm not sure what would have happened. I can try if you think that won't break anything.

@tidiegeler
Copy link
Contributor

Hi @mharbison72, thanks for your contribution. We're going to check soon whether there has been some kind of breaking change with an earlier Mercurial update causing the unit test failures on our (SCM-Manager) side. Until then, we'd let this merge request on hold (but reach out later on).

@mharbison72
Copy link
Contributor Author

@tidiegeler - sounds good. LMK if you need help deciphering something or understanding hg behavior changes. The command line interface is meant to be stable, barring some major issue. The contents of the file system aren't covered by that promise, and I vaguely recall at some point there was a change where empty directories that weren't previously getting deleted, started to a few years ago. I forget the details, but it may have been the purge extension. (Though this seems to be the opposite of the current failures.)

Copy link

stale bot commented Apr 26, 2025

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale Issue is stale and will be closed if no further activity occurs label Apr 26, 2025
@mharbison72
Copy link
Contributor Author

Adding activity so that it doesn't get closed.

@fscholdei fscholdei added pinned Pinnend issues are not touched by the stale bot and removed stale Issue is stale and will be closed if no further activity occurs labels Apr 28, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working pinned Pinnend issues are not touched by the stale bot
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants