Skip to content
This repository was archived by the owner on Mar 10, 2022. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
'use strict'

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

@slimsag @felixfbecker is this useful/necessary?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

https://stackoverflow.com/questions/31391760/use-strict-needed-in-a-typescript-file

We should enable the always strict TS compiler flag I guess

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

#17


import vscode from 'vscode'

export function getSourcegraphUrl(): string {
const url = vscode.workspace.getConfiguration('sourcegraph').get<string>('url')! // has default value
if (url.endsWith('/')) {
return url.slice(0, -1)
}
return url
}
90 changes: 5 additions & 85 deletions src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,92 +1,12 @@
'use strict'
import execa from 'execa'

import opn from 'opn'
import * as path from 'path'
import * as vscode from 'vscode'
import { getSourcegraphUrl } from './config'
import { repoInfo } from './git'

const VERSION = require('../package.json').version

/**
* Returns the names of all git remotes, e.g. ["origin", "foobar"]
*/
async function gitRemotes(repoDir: string): Promise<string[]> {
const { stdout } = await execa('git', ['remote'], { cwd: repoDir })
return stdout.split('\n')
}

/**
* Returns the remote URL for the given remote name.
* e.g. `origin` -> `git@github.com:foo/bar`
*/
async function gitRemoteURL(repoDir: string, remoteName: string): Promise<string> {
const { stdout } = await execa('git', ['remote', 'get-url', remoteName], { cwd: repoDir })
return stdout
}

/**
* Returns the remote URL of the first Git remote found.
*/
async function gitDefaultRemoteURL(repoDir: string): Promise<string> {
const remotes = await gitRemotes(repoDir)
if (remotes.length === 0) {
throw new Error('no configured git remotes')
}
if (remotes.length > 1) {
console.log('using first git remote:', remotes[0])
}
return await gitRemoteURL(repoDir, remotes[0])
}

/**
* Returns the repository root directory for any directory within the
* repository.
*/
async function gitRootDir(repoDir: string): Promise<string> {
const { stdout } = await execa('git', ['rev-parse', '--show-toplevel'], { cwd: repoDir })
return stdout
}

/**
* Returns either the current branch name of the repository OR in all
* other cases (e.g. detached HEAD state), it returns "HEAD".
*/
async function gitBranch(repoDir: string): Promise<string> {
const { stdout } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: repoDir })
return stdout
}

function sourcegraphURL(): string {
const url = vscode.workspace.getConfiguration('sourcegraph').get<string>('url')! // has default value
if (!url.endsWith('/')) {
return url + '/'
}
return url
}

/**
* Returns the Sourcegraph repository URI, and the file path relative
* to the repository root. If the repository URI cannot be determined, empty
* strings are returned.
*/
async function repoInfo(fileName: string): Promise<[string, string, string]> {
let remoteURL = ''
let branch = ''
let fileRel = ''
try {
// Determine repository root directory.
const fileDir = path.dirname(fileName)
const repoRoot = await gitRootDir(fileDir)

// Determine file path, relative to repository root.
fileRel = fileName.slice(repoRoot.length + 1)
remoteURL = await gitDefaultRemoteURL(repoRoot)
branch = await gitBranch(repoRoot)
} catch (e) {
console.log('repoInfo:', e)
}
return [remoteURL, branch, fileRel]
}

/**
* Displays an error message to the user.
*/
Expand Down Expand Up @@ -117,7 +37,7 @@ async function openCommand(): Promise<void> {

// Open in browser.
await opn(
`${sourcegraphURL()}-/editor` +
`${getSourcegraphUrl()}-/editor` +
`?remote_url=${encodeURIComponent(remoteURL)}` +
`&branch=${encodeURIComponent(branch)}` +
`&file=${encodeURIComponent(fileRel)}` +
Expand Down Expand Up @@ -147,7 +67,7 @@ async function searchCommand(): Promise<void> {

// Search in browser.
await opn(
`${sourcegraphURL()}-/editor` +
`${getSourcegraphUrl()}-/editor` +
`?remote_url=${encodeURIComponent(remoteURL)}` +
`&branch=${encodeURIComponent(branch)}` +
`&file=${encodeURIComponent(fileRel)}` +
Expand Down
77 changes: 77 additions & 0 deletions src/git.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
'use strict'

import execa from 'execa'
import * as path from 'path'

/**
* Returns the names of all git remotes, e.g. ["origin", "foobar"]
*/
async function gitRemotes(repoDir: string): Promise<string[]> {
const { stdout } = await execa('git', ['remote'], { cwd: repoDir })
return stdout.split('\n')
}

/**
* Returns the remote URL for the given remote name.
* e.g. `origin` -> `git@github.com:foo/bar`
*/
async function gitRemoteURL(repoDir: string, remoteName: string): Promise<string> {
const { stdout } = await execa('git', ['remote', 'get-url', remoteName], { cwd: repoDir })
return stdout
}

/**
* Returns the remote URL of the first Git remote found.
*/
async function gitDefaultRemoteURL(repoDir: string): Promise<string> {
const remotes = await gitRemotes(repoDir)
if (remotes.length === 0) {
throw new Error('no configured git remotes')
}
if (remotes.length > 1) {
console.log('using first git remote:', remotes[0])
}
return await gitRemoteURL(repoDir, remotes[0])
}

/**
* Returns the repository root directory for any directory within the
* repository.
*/
async function gitRootDir(repoDir: string): Promise<string> {
const { stdout } = await execa('git', ['rev-parse', '--show-toplevel'], { cwd: repoDir })
return stdout
}

/**
* Returns either the current branch name of the repository OR in all
* other cases (e.g. detached HEAD state), it returns "HEAD".
*/
async function gitBranch(repoDir: string): Promise<string> {
const { stdout } = await execa('git', ['rev-parse', '--abbrev-ref', 'HEAD'], { cwd: repoDir })
return stdout
}

/**
* Returns the Sourcegraph repository URI, and the file path relative
* to the repository root. If the repository URI cannot be determined, empty
* strings are returned.
*/
export async function repoInfo(fileName: string): Promise<[string, string, string]> {
let remoteURL = ''
let branch = ''
let fileRel = ''
try {
// Determine repository root directory.
const fileDir = path.dirname(fileName)
const repoRoot = await gitRootDir(fileDir)

// Determine file path, relative to repository root.
fileRel = fileName.slice(repoRoot.length + 1)
remoteURL = await gitDefaultRemoteURL(repoRoot)
branch = await gitBranch(repoRoot)
} catch (e) {
console.log('repoInfo:', e)
}
return [remoteURL, branch, fileRel]
}