Skip to content

Commit 2c4d427

Browse files
committed
Merge remote-tracking branch 'upstream/main'
* upstream/main: Add missing variables Reformat BibTex in Show BibTex Source (#13761) Auto publish before JBang tests (#13779) Hotfix: calling of publish.yml Support BibLaTeX datamodel validations (#13693) Auto add and remove of "status: changes-required" label (#13778) New Crowdin updates (#13777) Restore local-only Git behavior for SLR to fix repository initialization error (#13775) Use vanilla hashset (#13771) Fix Springer Fetcher names (#13770) Fix condition Publish SNAPSHOT on jablib change (#13774) Adapt as per new set of checks (#13772) Bump jablib/src/main/resources/csl-styles from `1194364` to `17cfa60` (#13750)
2 parents c0d0a7c + 1472aa3 commit 2c4d427

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+283
-93
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: Adapt PR status labels
2+
3+
on:
4+
pull_request_review:
5+
types: [submitted]
6+
7+
jobs:
8+
label-changes-required:
9+
if: github.event.review.state == 'changes_requested'
10+
runs-on: ubuntu-latest
11+
steps:
12+
- name: Adapt labels
13+
run: |
14+
gh issue --repo ${{ github.repository }} edit ${{ github.event.pull_request.number }} --remove-label "status: ready-for-review"
15+
gh issue --repo ${{ github.repository }} edit ${{ github.event.pull_request.number }} --remove-label "status: awaiting-second-review"
16+
gh issue --repo ${{ github.repository }} edit ${{ github.event.pull_request.number }} --add-label "status: changes-required"
17+
env:
18+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/on-pr-opened-updated.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,12 @@ jobs:
160160
echo "✅ No merge conflicts"
161161
env:
162162
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
163+
remove_label:
164+
if: github.repository == 'JabRef/jabref'
165+
name: Remove label "status: changes-required"
166+
runs-on: ubuntu-latest
167+
steps:
168+
- run: gh issue --repo ${{ github.repository }} edit ${{ github.event.pull_request.number }} --remove-label "status: changes-required"
163169
upload-pr-number:
164170
if: github.repository == 'JabRef/jabref'
165171
runs-on: ubuntu-latest

.github/workflows/publish.yml

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
11
name: Publish to maven central
22

33
on:
4-
pull_request:
5-
paths:
6-
- .github/workflows/publish.yml
4+
# On releases
75
push:
8-
paths:
9-
- .github/workflows/publish.yml
106
tags:
11-
- '*'
12-
schedule:
13-
# run on each Monday
14-
- cron: '2 3 * * 1'
7+
- '**'
8+
9+
# Called by the JBang testing jobs to ensure that SNAPSHOT is uptodate
10+
workflow_call:
11+
secrets:
12+
KOPPOR_SIGNING_SECRETKEYRINGFILE_BASE64:
13+
required: true
14+
KOPPOR_SIGNING_KEYID:
15+
required: true
16+
KOPPOR_SIGNING_PASSWORD:
17+
required: true
18+
KOPPOR_MAVENCENTRALUSERNAME:
19+
required: true
20+
KOPPOR_MAVENCENTRALPASSWORD:
21+
required: true
22+
1523
workflow_dispatch:
1624
inputs:
1725
tagbuild:
@@ -20,6 +28,11 @@ on:
2028
default: false
2129
type: boolean
2230

31+
# Additional run in addition to the other events, because some resources could have changes
32+
schedule:
33+
# Run on each Monday
34+
- cron: '2 3 * * 1'
35+
2336
permissions:
2437
actions: write
2538
contents: read
@@ -34,9 +47,33 @@ concurrency:
3447
cancel-in-progress: true
3548

3649
jobs:
50+
detect_changes:
51+
runs-on: ubuntu-latest
52+
outputs:
53+
changed: ${{ steps.changed.outputs.any_changed }}
54+
steps:
55+
- uses: actions/checkout@v5
56+
with:
57+
fetch-depth: 0
58+
- name: Detect changed jablib classes or workflow
59+
id: changed
60+
uses: tj-actions/changed-files@v45
61+
with:
62+
files: |
63+
jablib/src/main/java/**/*.java
64+
.github/workflows/publish.yml
65+
3766
publish:
3867
name: jablib
39-
if: github.repository == 'JabRef/jabref'
68+
needs: detect_changes
69+
if: >
70+
github.event_name == 'schedule' ||
71+
github.event_name == 'workflow_dispatch' ||
72+
(needs.detect_changes.outputs.changed == 'true' &&
73+
((github.event_name == 'workflow_call' && github.repository == 'JabRef/jabref') ||
74+
(github.event_name == 'push' && github.repository == 'JabRef/jabref') ||
75+
(github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == 'JabRef/jabref'))
76+
)
4077
runs-on: ubuntu-latest
4178
steps:
4279
- name: Fetch all history for all tags and branches

.github/workflows/tests-code.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ concurrency:
2222
cancel-in-progress: true
2323

2424
permissions:
25+
# required for publish.yml
26+
actions: write
27+
contents: read
2528
pull-requests: write
2629

2730
jobs:
@@ -393,9 +396,20 @@ jobs:
393396
CI: "true"
394397
DBMS: "postgresql"
395398

399+
publish:
400+
if: github.ref == 'refs/heads/main'
401+
uses: ./.github/workflows/publish.yml
402+
secrets:
403+
KOPPOR_SIGNING_SECRETKEYRINGFILE_BASE64: ${{ secrets.KOPPOR_SIGNING_SECRETKEYRINGFILE_BASE64 }}
404+
KOPPOR_SIGNING_KEYID: ${{ secrets.KOPPOR_SIGNING_KEYID }}
405+
KOPPOR_SIGNING_PASSWORD: ${{ secrets.KOPPOR_SIGNING_PASSWORD }}
406+
KOPPOR_MAVENCENTRALUSERNAME: ${{ secrets.KOPPOR_MAVENCENTRALUSERNAME }}
407+
KOPPOR_MAVENCENTRALPASSWORD: ${{ secrets.KOPPOR_MAVENCENTRALPASSWORD }}
408+
396409
jbang:
397410
name: JBang (main)
398411
runs-on: ubuntu-latest
412+
needs: publish
399413
if: github.ref == 'refs/heads/main'
400414
steps:
401415
- name: Checkout source
@@ -431,6 +445,7 @@ jobs:
431445
jbang-pr:
432446
name: JBang (PR)
433447
runs-on: ubuntu-latest
448+
# does not need publish, because the JBang scripts are modified
434449
if: github.ref != 'refs/heads/main'
435450
strategy:
436451
fail-fast: false

.github/workflows/tests-pr.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ jobs:
127127
128128
LINE_COUNT=$(echo "$BOXES" | wc -l)
129129
130-
if [ "$LINE_COUNT" -ne 7 ]; then
131-
echo "❌ Found $LINE_COUNT lines instead of 7 required lines"
130+
if [ "$LINE_COUNT" -ne 6 ]; then
131+
echo "❌ Found $LINE_COUNT lines instead of 6 required lines"
132132
exit 1
133133
fi
134134

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
3232
- When relativizing file names, symlinks are now taken into account. [#12995](https://github.com/JabRef/jabref/issues/12995)
3333
- We added a new button for shortening the DOI near the DOI field in the general tab when viewing an entry. [#13639](https://github.com/JabRef/jabref/issues/13639)
3434
- We added support for finding CSL-Styles based on their short title (e.g. apa instead of "american psychological association"). [#13728](https://github.com/JabRef/jabref/pull/13728)
35+
- We added BibLaTeX datamodel validation support in order to improve error message quality in entries' fields validation. [#13318](https://github.com/JabRef/jabref/issues/13318)
3536

3637
### Changed
3738

@@ -72,6 +73,7 @@ Note that this project **does not** adhere to [Semantic Versioning](https://semv
7273
- We improved JabRef's internal document viewer. It now allows text section, searching and highlighting of search terms and page rotation [#13193](https://github.com/JabRef/jabref/pull/13193).
7374
- When importing a PDF, there is no empty entry column shown in the multi merge dialog. [#13132](https://github.com/JabRef/jabref/issues/13132)
7475
- We added a progress dialog to the "Check consistency" action and progress output to the corresponding cli command. [#12487](https://github.com/JabRef/jabref/issues/12487)
76+
- The BibTeX source is now formatted using the JabRef style at the import inspection dialog. [#13015](https://github.com/JabRef/jabref/issues/13015)
7577
- We made the `check-consistency` command of the toolkit always return an exit code; 0 means no issues found, a non-zero exit code reflects any issues, which allows CI to fail in these cases [#13328](https://github.com/JabRef/jabref/issues/13328).
7678
- We changed the validation error dialog for overriding the default file directories to a confirmation dialog for saving other preferences under the library properties. [#13488](https://github.com/JabRef/jabref/pull/13488)
7779
- We made the copy sub menu on the context menu consistent with the copy sub menu at "Edit". [#13280](https://github.com/JabRef/jabref/pull/13280)

jabgui/src/main/java/org/jabref/gui/importer/ImportEntriesViewModel.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,11 @@ public String getSourceString(BibEntry entry) {
125125
BibWriter bibWriter = new BibWriter(writer, OS.NEWLINE);
126126
FieldWriter fieldWriter = FieldWriter.buildIgnoreHashes(preferences.getFieldPreferences());
127127
try {
128-
new BibEntryWriter(fieldWriter, entryTypesManager).write(entry, bibWriter, selectedDb.getValue().getMode());
128+
// Force reformatting so the displayed BibTeX is consistently formatted
129+
new BibEntryWriter(fieldWriter, entryTypesManager).write(entry, bibWriter, selectedDb.getValue().getMode(), true);
129130
} catch (IOException ioException) {
130-
return "";
131+
// In case of error, fall back to the original parsed serialization if available
132+
return entry.getParsedSerialization();
131133
}
132134
return writer.toString();
133135
}

jabgui/src/main/java/org/jabref/gui/slr/ManageStudyDefinitionViewModel.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
import org.jabref.logic.importer.fetcher.CompositeSearchBasedFetcher;
2929
import org.jabref.logic.importer.fetcher.DBLPFetcher;
3030
import org.jabref.logic.importer.fetcher.IEEE;
31-
import org.jabref.logic.importer.fetcher.SpringerFetcher;
31+
import org.jabref.logic.importer.fetcher.SpringerNatureWebFetcher;
3232
import org.jabref.logic.l10n.Localization;
3333
import org.jabref.model.study.Study;
3434
import org.jabref.model.study.StudyDatabase;
@@ -48,7 +48,7 @@ public class ManageStudyDefinitionViewModel {
4848
private static final Set<String> DEFAULT_SELECTION = Set.of(
4949
ACMPortalFetcher.FETCHER_NAME,
5050
IEEE.FETCHER_NAME,
51-
SpringerFetcher.FETCHER_NAME,
51+
SpringerNatureWebFetcher.FETCHER_NAME,
5252
DBLPFetcher.FETCHER_NAME);
5353

5454
private final StringProperty title = new SimpleStringProperty();

jabgui/src/main/java/org/jabref/gui/slr/StartNewStudyAction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,9 @@ protected void crawlPreparation(Path studyRepositoryRoot) throws IOException, Gi
6464
// The GitHandler is already called to initialize the repository with one single commit "Initial commit".
6565
// The "Initial commit" should also contain the created YAML.
6666
// Thus, we append to that commit.
67-
new GitHandler(studyRepositoryRoot).createCommitOnCurrentBranch("Initial commit", true);
67+
GitHandler gitHandler = new GitHandler(studyRepositoryRoot);
68+
gitHandler.initIfNeeded();
69+
gitHandler.createCommitOnCurrentBranch("Initial commit", true);
6870
}
6971

7072
@Override

jablib/src/main/java/org/jabref/logic/biblog/BibtexLogParser.java

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import java.io.IOException;
44
import java.nio.file.Files;
55
import java.nio.file.Path;
6-
import java.util.ArrayList;
76
import java.util.List;
87
import java.util.Optional;
98
import java.util.regex.Matcher;
@@ -19,52 +18,88 @@
1918
* Parses the contents of a .blg (BibTeX log) file to extract warning messages.
2019
*/
2120
public class BibtexLogParser {
22-
private static final Pattern WARNING_PATTERN = Pattern.compile("^Warning--(?<message>[a-zA-Z ]+) in (?<entryKey>[^\\s]+)$");
21+
private static final Pattern BIBTEX_WARNING_PATTERN = Pattern.compile("^Warning--(?<message>[a-zA-Z ]+) in (?<entryKey>[^\\s]+)$");
22+
private static final Pattern BIBLATEX_WARNING_PATTERN = Pattern.compile(
23+
"(?:(?:\\[\\d+\\] )?Biber\\.pm:\\d+> )?WARN - Datamodel: [a-z]+ entry '(?<entryKey>[^']+)' \\((?<fileName>[^)]+)\\): (?<message>.+)");
24+
2325
private static final String EMPTY_FIELD_PREFIX = "empty";
26+
private static final String INVALID_FIELD_PREFIX = "field '";
27+
private static final String MULTI_INVALID_FIELD_PREFIX = "field - one of '";
2428

2529
public List<BibWarning> parseBiblog(@NonNull Path blgFilePath) throws IOException {
26-
List<BibWarning> warnings = new ArrayList<>();
27-
List<String> lines = Files.readAllLines(blgFilePath);
28-
for (String line : lines) {
29-
Optional<BibWarning> potentialWarning = parseWarningLine(line);
30-
potentialWarning.ifPresent(warnings::add);
31-
}
32-
return warnings;
30+
return Files.lines(blgFilePath)
31+
.map(this::parseWarningLine)
32+
.flatMap(Optional::stream)
33+
.toList();
3334
}
3435

35-
/**
36-
* Parses a single line from the .blg file to identify a warning.
37-
* <p>
38-
* Currently supports parsing warnings of the format:
39-
* <pre>
40-
* Warning--[message] in [entryKey]
41-
* </pre>
42-
* For example: {@code Warning--empty journal in Scholey_2013}
43-
*
44-
* @param line a single line from the .blg file
45-
* @return an Optional containing a {@link BibWarning} if a match is found, or empty otherwise
46-
*/
47-
private Optional<BibWarning> parseWarningLine(String line) {
48-
// TODO: Support additional warning formats
49-
Matcher matcher = WARNING_PATTERN.matcher(line);
50-
if (!matcher.find()) {
51-
return Optional.empty();
36+
/// Parses a single line from a .blg file to identify a warning.
37+
///
38+
/// This method supports two warning formats:
39+
///
40+
/// 1. **BibTeX Warnings:** Simple warnings from the legacy BibTeX backend.
41+
/// `Warning--[message] in [entryKey]`
42+
/// For example: `Warning--empty journal in Scholey_2013`
43+
///
44+
/// 2. **BibLaTeX Datamodel Warnings:** Detailed warnings from the Biber backend, including datamodel validation issues.
45+
/// `[Log line] > WARN - Datamodel: [entry type] entry '[entryKey]' ([fileName]): [message]`
46+
/// For example: `Biber.pm:123> WARN - Datamodel: article entry 'Scholey_2013' (file.bib): Invalid field 'journal'`
47+
///
48+
/// @param line The single line from the .blg file to parse.
49+
///
50+
/// @returns An `Optional` containing a `BibWarning` if a match is found, or an empty `Optional` otherwise.
51+
Optional<BibWarning> parseWarningLine(String line) {
52+
Matcher bibtexMatcher = BIBTEX_WARNING_PATTERN.matcher(line);
53+
if (bibtexMatcher.find()) {
54+
String message = bibtexMatcher.group("message").trim();
55+
String entryKey = bibtexMatcher.group("entryKey");
56+
// Extract field name for warnings related to empty fields (e.g., "empty journal" -> fieldName = "journal")
57+
String fieldName = null;
58+
if (message.startsWith(EMPTY_FIELD_PREFIX)) {
59+
fieldName = message.substring(EMPTY_FIELD_PREFIX.length()).trim();
60+
fieldName = FieldFactory.parseField(fieldName).getName();
61+
}
62+
63+
return Optional.of(new BibWarning(
64+
SeverityType.WARNING,
65+
message,
66+
fieldName,
67+
entryKey
68+
));
5269
}
5370

54-
String message = matcher.group("message").trim();
55-
String entryKey = matcher.group("entryKey");
56-
// Extract field name for warnings related to empty fields (e.g., "empty journal" -> fieldName = "journal")
57-
String fieldName = null;
58-
if (message.startsWith(EMPTY_FIELD_PREFIX)) {
59-
fieldName = message.substring(EMPTY_FIELD_PREFIX.length()).trim();
60-
fieldName = FieldFactory.parseField(fieldName).getName();
71+
Matcher biblatexMatcher = BIBLATEX_WARNING_PATTERN.matcher(line);
72+
if (biblatexMatcher.find()) {
73+
String message = biblatexMatcher.group("message").trim();
74+
String entryKey = biblatexMatcher.group("entryKey");
75+
String fieldName = null;
76+
77+
// Extract field name for warnings related to invalid fields (e.g., "Invalid field 'publisher' for entrytype 'article'" -> fieldName = "publisher")
78+
String lowerCaseMessage = message.toLowerCase();
79+
if (lowerCaseMessage.contains(INVALID_FIELD_PREFIX)) {
80+
int startIndex = lowerCaseMessage.indexOf(INVALID_FIELD_PREFIX) + INVALID_FIELD_PREFIX.length();
81+
int endIndex = lowerCaseMessage.indexOf('\'', startIndex);
82+
if (endIndex != -1) {
83+
fieldName = lowerCaseMessage.substring(startIndex, endIndex).trim();
84+
fieldName = FieldFactory.parseField(fieldName).getName();
85+
}
86+
} else if (lowerCaseMessage.contains(MULTI_INVALID_FIELD_PREFIX)) {
87+
int startIndex = lowerCaseMessage.indexOf(MULTI_INVALID_FIELD_PREFIX) + MULTI_INVALID_FIELD_PREFIX.length();
88+
int endIndex = lowerCaseMessage.indexOf('\'', startIndex);
89+
if (endIndex != -1) {
90+
fieldName = lowerCaseMessage.substring(startIndex, endIndex).trim().split(",")[0].trim();
91+
fieldName = FieldFactory.parseField(fieldName).getName();
92+
}
93+
}
94+
95+
return Optional.of(new BibWarning(
96+
SeverityType.WARNING,
97+
message,
98+
fieldName,
99+
entryKey
100+
));
61101
}
62102

63-
return Optional.of(new BibWarning(
64-
SeverityType.WARNING,
65-
message,
66-
fieldName,
67-
entryKey
68-
));
103+
return Optional.empty();
69104
}
70105
}

0 commit comments

Comments
 (0)