WARNING: THIS SITE IS A MIRROR OF GITHUB.COM / IT CANNOT LOGIN OR REGISTER ACCOUNTS / THE CONTENTS ARE PROVIDED AS-IS / THIS SITE ASSUMES NO RESPONSIBILITY FOR ANY DISPLAYED CONTENT OR LINKS / IF YOU FOUND SOMETHING MAY NOT GOOD FOR EVERYONE, CONTACT ADMIN AT ilovescratch@foxmail.com
Skip to content

Commit 20d1c6d

Browse files
authored
Merge branch 'main' into lunny/refactor_clone_push
2 parents 046b65c + ed698d1 commit 20d1c6d

File tree

6 files changed

+69
-15
lines changed

6 files changed

+69
-15
lines changed

modules/setting/config_provider.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -337,14 +337,14 @@ func LogStartupProblem(skip int, level log.Level, format string, args ...any) {
337337

338338
func deprecatedSetting(rootCfg ConfigProvider, oldSection, oldKey, newSection, newKey, version string) {
339339
if rootCfg.Section(oldSection).HasKey(oldKey) {
340-
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
340+
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` present, please use `[%s].%s` instead because this fallback will be/has been removed in %s", oldSection, oldKey, newSection, newKey, version)
341341
}
342342
}
343343

344344
// deprecatedSettingDB add a hint that the configuration has been moved to database but still kept in app.ini
345345
func deprecatedSettingDB(rootCfg ConfigProvider, oldSection, oldKey string) {
346346
if rootCfg.Section(oldSection).HasKey(oldKey) {
347-
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` presents but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey)
347+
LogStartupProblem(1, log.ERROR, "Deprecation: config option `[%s].%s` present but it won't take effect because it has been moved to admin panel -> config setting", oldSection, oldKey)
348348
}
349349
}
350350

services/context/csrf.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func (c *csrfProtector) PrepareForSessionUser(ctx *Context) {
118118
if uidChanged {
119119
_ = ctx.Session.Set(c.opt.oldSessionKey, c.id)
120120
} else if cookieToken != "" {
121-
// If cookie token presents, re-use existing unexpired token, else generate a new one.
121+
// If cookie token present, re-use existing unexpired token, else generate a new one.
122122
if issueTime, ok := ParseCsrfToken(cookieToken); ok {
123123
dur := time.Since(issueTime) // issueTime is not a monotonic-clock, the server time may change a lot to an early time.
124124
if dur >= -CsrfTokenRegenerationInterval && dur <= CsrfTokenRegenerationInterval {

services/migrations/migrate.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
repo_model "code.gitea.io/gitea/models/repo"
1717
system_model "code.gitea.io/gitea/models/system"
1818
user_model "code.gitea.io/gitea/models/user"
19+
"code.gitea.io/gitea/modules/container"
1920
"code.gitea.io/gitea/modules/git"
2021
"code.gitea.io/gitea/modules/hostmatcher"
2122
"code.gitea.io/gitea/modules/log"
@@ -327,6 +328,9 @@ func migrateRepository(ctx context.Context, doer *user_model.User, downloader ba
327328
messenger("repo.migrate.migrating_issues")
328329
issueBatchSize := uploader.MaxBatchInsertSize("issue")
329330

331+
// because when the migrating is running, some issues maybe removed, so after the next page
332+
// some of issue maybe duplicated, so we need to record the inserted issue indexes
333+
mapInsertedIssueIndexes := container.Set[int64]{}
330334
for i := 1; ; i++ {
331335
issues, isEnd, err := downloader.GetIssues(ctx, i, issueBatchSize)
332336
if err != nil {
@@ -336,6 +340,14 @@ func migrateRepository(ctx context.Context, doer *user_model.User, downloader ba
336340
log.Warn("migrating issues is not supported, ignored")
337341
break
338342
}
343+
for i := 0; i < len(issues); i++ {
344+
if mapInsertedIssueIndexes.Contains(issues[i].Number) {
345+
issues = append(issues[:i], issues[i+1:]...)
346+
i--
347+
continue
348+
}
349+
mapInsertedIssueIndexes.Add(issues[i].Number)
350+
}
339351

340352
if err := uploader.CreateIssues(ctx, issues...); err != nil {
341353
return err
@@ -381,6 +393,7 @@ func migrateRepository(ctx context.Context, doer *user_model.User, downloader ba
381393
log.Trace("migrating pull requests and comments")
382394
messenger("repo.migrate.migrating_pulls")
383395
prBatchSize := uploader.MaxBatchInsertSize("pullrequest")
396+
mapInsertedPRIndexes := container.Set[int64]{}
384397
for i := 1; ; i++ {
385398
prs, isEnd, err := downloader.GetPullRequests(ctx, i, prBatchSize)
386399
if err != nil {
@@ -390,6 +403,14 @@ func migrateRepository(ctx context.Context, doer *user_model.User, downloader ba
390403
log.Warn("migrating pull requests is not supported, ignored")
391404
break
392405
}
406+
for i := 0; i < len(prs); i++ {
407+
if mapInsertedPRIndexes.Contains(prs[i].Number) {
408+
prs = append(prs[:i], prs[i+1:]...)
409+
i--
410+
continue
411+
}
412+
mapInsertedPRIndexes.Add(prs[i].Number)
413+
}
393414

394415
if err := uploader.CreatePullRequests(ctx, prs...); err != nil {
395416
return err

web_src/js/features/comp/ComboMarkdownEditor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import {POST} from '../../modules/fetch.ts';
1717
import {
1818
EventEditorContentChanged,
1919
initTextareaMarkdown,
20-
textareaInsertText,
20+
replaceTextareaSelection,
2121
triggerEditorContentChanged,
2222
} from './EditorMarkdown.ts';
2323
import {DropzoneCustomEventReloadFiles, initDropzone} from '../dropzone.ts';
@@ -273,7 +273,7 @@ export class ComboMarkdownEditor {
273273
let cols = parseInt(addTablePanel.querySelector<HTMLInputElement>('[name=cols]')!.value);
274274
rows = Math.max(1, Math.min(100, rows));
275275
cols = Math.max(1, Math.min(100, cols));
276-
textareaInsertText(this.textarea, `\n${this.generateMarkdownTable(rows, cols)}\n\n`);
276+
replaceTextareaSelection(this.textarea, `\n${this.generateMarkdownTable(rows, cols)}\n\n`);
277277
addTablePanelTippy.hide();
278278
});
279279
}

web_src/js/features/comp/EditorMarkdown.ts

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,23 @@ export function triggerEditorContentChanged(target: HTMLElement) {
44
target.dispatchEvent(new CustomEvent(EventEditorContentChanged, {bubbles: true}));
55
}
66

7-
export function textareaInsertText(textarea: HTMLTextAreaElement, value: string) {
8-
const startPos = textarea.selectionStart;
9-
const endPos = textarea.selectionEnd;
10-
textarea.value = textarea.value.substring(0, startPos) + value + textarea.value.substring(endPos);
11-
textarea.selectionStart = startPos;
12-
textarea.selectionEnd = startPos + value.length;
7+
/** replace selected text or insert text by creating a new edit history entry,
8+
* e.g. CTRL-Z works after this */
9+
export function replaceTextareaSelection(textarea: HTMLTextAreaElement, text: string) {
10+
const before = textarea.value.slice(0, textarea.selectionStart);
11+
const after = textarea.value.slice(textarea.selectionEnd);
12+
1313
textarea.focus();
14-
triggerEditorContentChanged(textarea);
14+
let success = false;
15+
try {
16+
success = document.execCommand('insertText', false, text); // eslint-disable-line @typescript-eslint/no-deprecated
17+
} catch {}
18+
19+
// fall back to regular replacement
20+
if (!success) {
21+
textarea.value = `${before}${text}${after}`;
22+
triggerEditorContentChanged(textarea);
23+
}
1524
}
1625

1726
type TextareaValueSelection = {
@@ -176,7 +185,7 @@ export function markdownHandleIndention(tvs: TextareaValueSelection): MarkdownHa
176185
return {handled: true, valueSelection: {value: linesBuf.lines.join('\n'), selStart: newPos, selEnd: newPos}};
177186
}
178187

179-
function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
188+
function handleNewline(textarea: HTMLTextAreaElement, e: KeyboardEvent) {
180189
const ret = markdownHandleIndention({value: textarea.value, selStart: textarea.selectionStart, selEnd: textarea.selectionEnd});
181190
if (!ret.handled || !ret.valueSelection) return; // FIXME: the "handled" seems redundant, only valueSelection is enough (null for unhandled)
182191
e.preventDefault();
@@ -185,6 +194,28 @@ function handleNewline(textarea: HTMLTextAreaElement, e: Event) {
185194
triggerEditorContentChanged(textarea);
186195
}
187196

197+
// Keys that act as dead keys will not work because the spec dictates that such keys are
198+
// emitted as `Dead` in e.key instead of the actual key.
199+
const pairs = new Map<string, string>([
200+
["'", "'"],
201+
['"', '"'],
202+
['`', '`'],
203+
['(', ')'],
204+
['[', ']'],
205+
['{', '}'],
206+
['<', '>'],
207+
]);
208+
209+
function handlePairCharacter(textarea: HTMLTextAreaElement, e: KeyboardEvent): void {
210+
const selStart = textarea.selectionStart;
211+
const selEnd = textarea.selectionEnd;
212+
if (selEnd === selStart) return; // do not process when no selection
213+
e.preventDefault();
214+
const inner = textarea.value.substring(selStart, selEnd);
215+
replaceTextareaSelection(textarea, `${e.key}${inner}${pairs.get(e.key)}`);
216+
textarea.setSelectionRange(selStart + 1, selEnd + 1);
217+
}
218+
188219
function isTextExpanderShown(textarea: HTMLElement): boolean {
189220
return Boolean(textarea.closest('text-expander')?.querySelector('.suggestions'));
190221
}
@@ -198,6 +229,8 @@ export function initTextareaMarkdown(textarea: HTMLTextAreaElement) {
198229
} else if (e.key === 'Enter' && !e.shiftKey && !e.ctrlKey && !e.metaKey && !e.altKey) {
199230
// use Enter to insert a new line with the same indention and prefix
200231
handleNewline(textarea, e);
232+
} else if (pairs.has(e.key)) {
233+
handlePairCharacter(textarea, e);
201234
}
202235
});
203236
}

web_src/js/features/comp/EditorUpload.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {imageInfo} from '../../utils/image.ts';
2-
import {textareaInsertText, triggerEditorContentChanged} from './EditorMarkdown.ts';
2+
import {replaceTextareaSelection, triggerEditorContentChanged} from './EditorMarkdown.ts';
33
import {
44
DropzoneCustomEventRemovedFile,
55
DropzoneCustomEventUploadDone,
@@ -43,7 +43,7 @@ class TextareaEditor {
4343
}
4444

4545
insertPlaceholder(value: string) {
46-
textareaInsertText(this.editor, value);
46+
replaceTextareaSelection(this.editor, value);
4747
}
4848

4949
replacePlaceholder(oldVal: string, newVal: string) {

0 commit comments

Comments
 (0)