mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-07 01:25:38 -05:00
Merge from vscode 93309f060778f6480a7d2a13913e6e7c624e9bc7
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { promises as fs, exists } from 'fs';
|
||||
import { promises as fs, exists, realpath } from 'fs';
|
||||
import * as path from 'path';
|
||||
import * as os from 'os';
|
||||
import * as cp from 'child_process';
|
||||
@@ -21,6 +21,7 @@ import { StringDecoder } from 'string_decoder';
|
||||
|
||||
// https://github.com/microsoft/vscode/issues/65693
|
||||
const MAX_CLI_LENGTH = 30000;
|
||||
const isWindows = process.platform === 'win32';
|
||||
|
||||
export interface IGit {
|
||||
path: string;
|
||||
@@ -419,8 +420,40 @@ export class Git {
|
||||
|
||||
async getRepositoryRoot(repositoryPath: string): Promise<string> {
|
||||
const result = await this.exec(repositoryPath, ['rev-parse', '--show-toplevel']);
|
||||
|
||||
// Keep trailing spaces which are part of the directory name
|
||||
return path.normalize(result.stdout.trimLeft().replace(/(\r\n|\r|\n)+$/, ''));
|
||||
const repoPath = path.normalize(result.stdout.trimLeft().replace(/(\r\n|\r|\n)+$/, ''));
|
||||
|
||||
if (isWindows) {
|
||||
// On Git 2.25+ if you call `rev-parse --show-toplevel` on a mapped drive, instead of getting the mapped drive path back, you get the UNC path for the mapped drive.
|
||||
// So we will try to normalize it back to the mapped drive path, if possible
|
||||
const repoUri = Uri.file(repoPath);
|
||||
const pathUri = Uri.file(repositoryPath);
|
||||
if (repoUri.authority.length !== 0 && pathUri.authority.length === 0) {
|
||||
let match = /(?<=^\/?)([a-zA-Z])(?=:\/)/.exec(pathUri.path);
|
||||
if (match !== null) {
|
||||
const [, letter] = match;
|
||||
|
||||
try {
|
||||
const networkPath = await new Promise<string>(resolve =>
|
||||
realpath.native(`${letter}:`, { encoding: 'utf8' }, (err, resolvedPath) =>
|
||||
// eslint-disable-next-line eqeqeq
|
||||
resolve(err != null ? undefined : resolvedPath),
|
||||
),
|
||||
);
|
||||
if (networkPath !== undefined) {
|
||||
return path.normalize(
|
||||
repoUri.fsPath.replace(networkPath, `${letter.toLowerCase()}:`),
|
||||
);
|
||||
}
|
||||
} catch { }
|
||||
}
|
||||
|
||||
return path.normalize(pathUri.fsPath);
|
||||
}
|
||||
}
|
||||
|
||||
return repoPath;
|
||||
}
|
||||
|
||||
async getRepositoryDotGit(repositoryPath: string): Promise<string> {
|
||||
|
||||
@@ -4,19 +4,13 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nls from 'vscode-nls';
|
||||
import * as dayjs from 'dayjs';
|
||||
import * as advancedFormat from 'dayjs/plugin/advancedFormat';
|
||||
import { CancellationToken, Disposable, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode';
|
||||
import { CancellationToken, Disposable, env, Event, EventEmitter, ThemeIcon, Timeline, TimelineChangeEvent, TimelineItem, TimelineOptions, TimelineProvider, Uri, workspace } from 'vscode';
|
||||
import { Model } from './model';
|
||||
import { Repository, Resource } from './repository';
|
||||
import { debounce } from './decorators';
|
||||
|
||||
dayjs.extend(advancedFormat);
|
||||
|
||||
const localize = nls.loadMessageBundle();
|
||||
|
||||
// TODO@eamodio: Localize or use a setting for date format
|
||||
|
||||
export class GitTimelineItem extends TimelineItem {
|
||||
static is(item: TimelineItem): item is GitTimelineItem {
|
||||
return item instanceof GitTimelineItem;
|
||||
@@ -145,16 +139,15 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
commits.splice(commits.length - 1, 1);
|
||||
}
|
||||
|
||||
let dateFormatter: dayjs.Dayjs;
|
||||
const dateFormatter = new Intl.DateTimeFormat(env.language, { year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric' });
|
||||
|
||||
const items = commits.map<GitTimelineItem>((c, i) => {
|
||||
const date = c.commitDate; // c.authorDate
|
||||
|
||||
dateFormatter = dayjs(date);
|
||||
|
||||
const item = new GitTimelineItem(c.hash, commits[i + 1]?.hash ?? `${c.hash}^`, c.message, date?.getTime() ?? 0, c.hash, 'git:file:commit');
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = c.authorName;
|
||||
item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format('MMMM Do, YYYY h:mma')}\n\n${c.message}`;
|
||||
item.detail = `${c.authorName} (${c.authorEmail}) \u2014 ${c.hash.substr(0, 8)}\n${dateFormatter.format(date)}\n\n${c.message}`;
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: 'git.timeline.openDiff',
|
||||
@@ -170,13 +163,12 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
const index = repo.indexGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath);
|
||||
if (index) {
|
||||
const date = this.repoStatusDate ?? new Date();
|
||||
dateFormatter = dayjs(date);
|
||||
|
||||
const item = new GitTimelineItem('~', 'HEAD', localize('git.timeline.stagedChanges', 'Staged Changes'), date.getTime(), 'index', 'git:file:index');
|
||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = '';
|
||||
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(index.type));
|
||||
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.index', 'Index'), dateFormatter.format(date), Resource.getStatusText(index.type));
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: 'git.timeline.openDiff',
|
||||
@@ -189,13 +181,12 @@ export class GitTimelineProvider implements TimelineProvider {
|
||||
const working = repo.workingTreeGroup.resourceStates.find(r => r.resourceUri.fsPath === uri.fsPath);
|
||||
if (working) {
|
||||
const date = new Date();
|
||||
dateFormatter = dayjs(date);
|
||||
|
||||
const item = new GitTimelineItem('', index ? '~' : 'HEAD', localize('git.timeline.uncommitedChanges', 'Uncommited Changes'), date.getTime(), 'working', 'git:file:working');
|
||||
// TODO@eamodio: Replace with a better icon -- reflecting its status maybe?
|
||||
item.iconPath = new (ThemeIcon as any)('git-commit');
|
||||
item.description = '';
|
||||
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format('MMMM Do, YYYY h:mma'), Resource.getStatusText(working.type));
|
||||
item.detail = localize('git.timeline.detail', '{0} \u2014 {1}\n{2}\n\n{3}', you, localize('git.workingTree', 'Working Tree'), dateFormatter.format(date), Resource.getStatusText(working.type));
|
||||
item.command = {
|
||||
title: 'Open Comparison',
|
||||
command: 'git.timeline.openDiff',
|
||||
|
||||
Reference in New Issue
Block a user