Skip to content

Commit

Permalink
Merge pull request #3 from iwatakeshi/develop
Browse files Browse the repository at this point in the history
v1.1.0-0
  • Loading branch information
iwatakeshi authored Nov 17, 2019
2 parents d9a53fb + 83de186 commit aa73194
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 29 deletions.
39 changes: 39 additions & 0 deletions src/utils/__test__/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { GitlyDownloadError, GitlyErrorType, GitlyExtractError, GitlyFetchError, GitlyUknownError } from '../error'

describe('utils/error', () => {
describe('GitlyFetchError', () => {
it('should return an instance', () => {
const error = new GitlyFetchError('message')
expect(error.message).toBe('[gitly:fetch]: message')
expect(error.code).toBe(-1)
expect(error.type).toBe(GitlyErrorType.Fetch)
})
})

describe('GitlyExtractError', () => {
it('should return an instance', () => {
const error = new GitlyExtractError('message')
expect(error.message).toBe('[gitly:extract]: message')
expect(error.code).toBe(-1)
expect(error.type).toBe(GitlyErrorType.Extract)
})
})

describe('GitlyDownloadError', () => {
it('should return an instance', () => {
const error = new GitlyDownloadError('message', 402)
expect(error.message).toBe('[gitly:download]: message')
expect(error.code).toBe(402)
expect(error.type).toBe(GitlyErrorType.Download)
})
})

describe('GitlyUknownError', () => {
it('should return an instance', () => {
const error = new GitlyUknownError('message', 402)
expect(error.message).toBe('[gitly:uknown]: message')
expect(error.code).toBe(402)
expect(error.type).toBe(GitlyErrorType.Unknown)
})
})
})
26 changes: 19 additions & 7 deletions src/utils/__test__/fetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ import { existsSync } from 'fs'
import { join } from 'path'
import { rm } from 'shelljs'

import { GitlyDownloadError } from '../error'
import fetch from '../fetch'

describe('utils/fetch', () => {
describe('utils/fetch (no cache)', () => {
const options = {
temp: join(__dirname, 'output', 'fetch', '.gitcopy')
}
Expand All @@ -17,67 +18,78 @@ describe('utils/fetch', () => {
})

it('should fetch "lukeed/gittar"', async () => {
expect.assertions(2)
const path = await fetch('lukeed/gittar', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "lukeed/gittar#v0.1.1"', async () => {
expect.assertions(2)
const path = await fetch('lukeed/gittar#v0.1.1', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "https://github.com/lukeed/gittar"', async () => {
expect.assertions(2)
const path = await fetch('https://github.com/lukeed/gittar', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})
it('should fetch "https://github.com/lukeed/gittar#v0.1.1"', async () => {
expect.assertions(2)
const path = await fetch('https://github.com/lukeed/gittar#v0.1.1', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "github.com/lukeed/gittar"', async () => {
expect.assertions(2)
const path = await fetch('github.com/lukeed/gittar', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "github.com/lukeed/gittar#v0.1.1"', async () => {
expect.assertions(2)
const path = await fetch('github.com/lukeed/gittar#v0.1.1', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "github:lukeed/gittar"', async () => {
expect.assertions(2)
const path = await fetch('github:lukeed/gittar', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "github:lukeed/gittar#v0.1.1"', async () => {
expect.assertions(2)
const path = await fetch('github:lukeed/gittar#v0.1.1', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should fetch "gitlab:Rich-Harris/buble#v0.15.2"', async () => {
expect.assertions(2)
const path = await fetch('gitlab:Rich-Harris/buble#v0.15.2', options)
expect(path).toBeTruthy()
expect(existsSync(path)).toBe(true)
})

it('should error and return an empty string when a repo is not found', async () => {
await expect(fetch('github:deekul:gittar#v0.1.1')).resolves.toEqual('').catch(error => expect(error).toEqual({
status: 404,
message: 'Not Found'
}))
it('should throw an error when a repo is not found', async () => {
expect.assertions(1)
try {
await fetch('github:doesnotexist123xyz/gittar#v0.1.1')
} catch (error) {
expect(error).toBeInstanceOf(GitlyDownloadError)
}
})
})

describe('utils/fetch (cache)', () => {
describe('utils/fetch (cached)', () => {
const options = {
temp: join(__dirname, 'output', 'fetch', 'cache'),
cache: true
Expand Down
26 changes: 14 additions & 12 deletions src/utils/download.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
import axios from 'axios'
import * as stream from 'stream'
import { promisify } from 'util'

import { GitlyDownloadError } from './error'
import write from './write'

const pipeline = promisify(stream.pipeline)

export default async function download(url: string, file: string): Promise<string> {
return new Promise(async (resolve, reject) => {
const response = await axios.get(url, {
responseType: 'stream',
validateStatus(status) {
return status >= 200 && status < 500
}
})
const status = response.status
if (status >= 400) reject({ status, message: response.statusText })
else if (status >= 300 && status < 400) {
return download(response.headers.location, file).then(resolve)
} else response.data.pipe(await write(file)).on('close', () => resolve(file))
const response = await axios.get(url, {
responseType: 'stream', validateStatus: status => status >= 200 && status < 500
})

const { statusText: message, status: code } = response
if (code >= 400) throw new GitlyDownloadError(message, code)
else if (code >= 300 && code < 400) {
return download(response.headers.location, file)
} else await pipeline(response.data, await write(file))
return file
}
39 changes: 39 additions & 0 deletions src/utils/error.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
export enum GitlyErrorType {
Fetch = 'fetch',
Extract = 'extract',
Download = 'download',
Unknown = 'unknown'
}

export default abstract class GitlyAbstractError extends Error {
static type: GitlyErrorType
type: GitlyErrorType
rawMessage: string
constructor(readonly message: string, readonly code: number = -1) {
super(message)
this.rawMessage = message
const type = this.type = this.ctor.type
this.message = `[${type ? `gitly:${type}` : 'gitly'}]: ${message}`
Object.setPrototypeOf(this, new.target.prototype)
}

get ctor(): typeof GitlyAbstractError {
return (this.constructor) as typeof GitlyAbstractError
}
}

export const GitlyUknownError = class extends GitlyAbstractError {
static type = GitlyErrorType.Unknown
}

export const GitlyFetchError = class extends GitlyAbstractError {
static type = GitlyErrorType.Fetch
}

export const GitlyExtractError = class extends GitlyAbstractError {
static type = GitlyErrorType.Extract
}

export const GitlyDownloadError = class extends GitlyAbstractError {
static type = GitlyErrorType.Download
}
14 changes: 5 additions & 9 deletions src/utils/fetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,10 @@ export default async (repository: string, options: GitlyOptions = {}) => {
order = [remote, local]
}

try {
const result = await execute(order)
if (typeof result === 'boolean') {
return file
}

return result
} catch (_) { }
const result = await execute(order)
if (typeof result === 'boolean') {
return file
}

return ''
return result
}
2 changes: 1 addition & 1 deletion src/utils/tar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export function getUrl(info: URLInfo, options: GitlyOptions = {}) {

export function getFile(info: URLInfo, options: GitlyOptions = {}) {
const { path, type, hostname: site } = info
return join(options.temp || join(os.homedir(), '.gitcopy'), site, path, `${type}.tar.gz`)
return join(options.temp || join(os.homedir(), '.gitly'), site, path, `${type}.tar.gz`)
}

export const extract = tar.extract

0 comments on commit aa73194

Please sign in to comment.