guito 0.6.0 → 0.6.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +37 -0
- package/bin/avatars.js +35 -0
- package/bin/guito-server.js +573 -7
- package/bin/repository-state.js +25 -0
- package/bin/ui/browser/index.html +1 -1
- package/bin/ui/browser/main-JDFRJ57Z.js +6 -0
- package/package.json +1 -1
- package/bin/ui/browser/main-GMXCXTX7.js +0 -6
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,43 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Guito are documented in this file. The project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html), and this changelog is structured around [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
|
|
5
|
+
## [0.6.2] - 2026-09-09
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Show author avatars in the commit table and the commit detail pane. Avatars are looked up by the author email on Gravatar, cached for a day, and fall back to initials when no image is available.
|
|
10
|
+
- Refresh Guito automatically when the repository changes. A lightweight probe runs every few seconds and whenever the window regains focus, detects commits, branches, tags, configuration, mailmap, and working tree changes made outside Guito (for example from a terminal or another tool), and then refreshes the history and the Uncommitted changes panel. History pages that were already loaded are kept, and the selected branch and commit stay valid after the refresh.
|
|
11
|
+
- Resize the Description column of the commit table by dragging, like the other columns. The chosen width is persisted across sessions together with the other column widths.
|
|
12
|
+
- Create draft pull requests with a "Create as draft" option in the Create Pull Request dialog.
|
|
13
|
+
- Move the commit search to the far right of the Guito title bar. The search box with its clear button, match counter, and previous/next navigation now sits next to the title instead of in the toolbar.
|
|
14
|
+
- Add the guito.autoReload setting (enabled by default) that controls whether Guito refreshes automatically as described above; it can also be set per repository in the server-side settings file.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Fill the window width with the commit table on load and when the window is resized: the Description column widens to absorb spare room, while resizing a column changes only that column and may leave the table narrower until the window is resized again. The saved widths act as minimums on narrow windows.
|
|
19
|
+
- The Uncommitted changes row shows your configured Git user name instead of "You", and commits display the author name from your Git configuration when the commit email matches it, while other authors and mailmap-rewritten names are left untouched.
|
|
20
|
+
- Tag suggestions in the Create Pull Request dialog now list labels already used by the repository's pull requests instead of Azure Boards work item tags.
|
|
21
|
+
- Reviewer, work item, and tag lookups in the Create Pull Request dialog show their own loading state and error message, cancel outdated requests while typing, and show a "No matches" hint instead of an empty list.
|
|
22
|
+
|
|
23
|
+
### Fixed
|
|
24
|
+
|
|
25
|
+
- Build pull request and pull request label URLs through the Azure DevOps repositories API so they resolve on Azure DevOps Server.
|
|
26
|
+
- Link work items to pull requests using the refs format Azure DevOps expects, and scope work item search to the current team project, accepting `#id` queries and returning at most 20 results.
|
|
27
|
+
- Strip `origin/` and `refs/heads/` prefixes from the pull request target branch before creating the pull request.
|
|
28
|
+
- Build Azure DevOps base URLs without duplicating collection path segments when the server URL path overlaps the remote repository path.
|
|
29
|
+
- Search reviewers through the collection identities API so the returned identities can be used directly as pull request reviewers.
|
|
30
|
+
|
|
31
|
+
## [0.6.1] - 2026-09-08
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- Rebase the current branch onto any branch from the pull menu. The new "Rebase (from)..." entry opens a branch picker with origin/main as the default choice, and the option list scrolls when a repository has many branches.
|
|
36
|
+
- Force push from the push menu. The red "Push (force)" entry asks for confirmation before overwriting the remote branch with the local history.
|
|
37
|
+
- Create pull requests on an on-prem Azure DevOps Server from the push menu. After setting the server URL with the new settings button (or the guito.azureDevOpsUrl VS Code setting), a "Create Pull Request..." entry opens a dialog with title, description, source and target branches, and shows a link to the created pull request when it is created.
|
|
38
|
+
- Fill pull requests with optional metadata: required and optional reviewers, linked work items searched by id or title, and tags, all with autocomplete suggestions from the Azure DevOps API.
|
|
39
|
+
- Create the pull request from a new remote branch with a random name without leaving the current branch, and publish the source branch to the remote automatically when it has not been pushed yet.
|
|
40
|
+
- Authenticate to Azure DevOps with Windows integrated authentication, so no credentials are stored or entered for on-prem servers.
|
|
41
|
+
|
|
5
42
|
## [0.6.0] - 2026-09-07
|
|
6
43
|
|
|
7
44
|
### Added
|
package/bin/avatars.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
export function avatarCache(fetchImage = fetch) {
|
|
3
|
+
const entries = new Map();
|
|
4
|
+
return (email) => {
|
|
5
|
+
const hash = createHash('sha256').update(email.trim().toLowerCase()).digest('hex');
|
|
6
|
+
const cached = entries.get(hash);
|
|
7
|
+
if (cached && cached.expires > Date.now())
|
|
8
|
+
return cached.image;
|
|
9
|
+
if (entries.size >= 500)
|
|
10
|
+
entries.delete(entries.keys().next().value);
|
|
11
|
+
const entry = { expires: Date.now() + 86400000, image: Promise.resolve(null) };
|
|
12
|
+
entry.image = (async () => {
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetchImage(`https://www.gravatar.com/avatar/${hash}?s=64&d=404`, {
|
|
15
|
+
signal: AbortSignal.timeout(5000),
|
|
16
|
+
});
|
|
17
|
+
if (response.status === 404)
|
|
18
|
+
return null;
|
|
19
|
+
if (!response.ok || !/^image\/(png|jpeg|gif|webp)/i.test(response.headers.get('content-type') ?? '')) {
|
|
20
|
+
throw new Error('Avatar unavailable');
|
|
21
|
+
}
|
|
22
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
23
|
+
if (buffer.length > 256000)
|
|
24
|
+
throw new Error('Avatar too large');
|
|
25
|
+
return { data: buffer, contentType: response.headers.get('content-type').split(';')[0] };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
entry.expires = Date.now() + 60000;
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
})();
|
|
32
|
+
entries.set(hash, entry);
|
|
33
|
+
return entry.image;
|
|
34
|
+
};
|
|
35
|
+
}
|