1+ import { EventEmitter } from "events" ;
12import { window } from "vscode" ;
23import * as cp from "child_process" ;
34import * as iconv from "iconv-lite" ;
45import * as jschardet from "jschardet" ;
5- import { EventEmitter } from "events" ;
6+ import * as path from 'path' ;
67
78interface CpOptions {
89 cwd ?: string ;
910 encoding ?: string ;
1011 log ?: boolean ;
1112}
1213
14+ export interface ISvn {
15+ path : string ;
16+ version : string ;
17+ }
18+
19+ function parseVersion ( raw : string ) : string {
20+ const match = raw . match ( / ( \d + \. \d + \. \d + \( r \d + \) ) / ) ;
21+
22+ if ( match && match [ 0 ] ) {
23+ return match [ 0 ] ;
24+ }
25+ return raw . split ( / [ \r \n ] + / ) [ 0 ] ;
26+ }
27+
28+ function findSpecificSvn ( path : string ) : Promise < ISvn > {
29+ return new Promise < ISvn > ( ( c , e ) => {
30+ const buffers : Buffer [ ] = [ ] ;
31+ const child = cp . spawn ( path , [ '--version' ] ) ;
32+ child . stdout . on ( 'data' , ( b : Buffer ) => buffers . push ( b ) ) ;
33+ // child.on('error', cpErrorHandler(e));
34+ child . on ( 'exit' , code => code ? e ( new Error ( 'Not found' ) ) : c ( { path, version : parseVersion ( Buffer . concat ( buffers ) . toString ( 'utf8' ) . trim ( ) ) } ) ) ;
35+ } ) ;
36+ }
37+
38+ function findSvnDarwin ( ) : Promise < ISvn > {
39+ return new Promise < ISvn > ( ( c , e ) => {
40+ cp . exec ( 'which svn' , ( err , svnPathBuffer ) => {
41+ if ( err ) {
42+ return e ( 'svn not found' ) ;
43+ }
44+
45+ const path = svnPathBuffer . toString ( ) . replace ( / ^ \s + | \s + $ / g, '' ) ;
46+
47+ function getVersion ( path : string ) {
48+ // make sure svn executes
49+ cp . exec ( 'svn --version' , ( err , stdout ) => {
50+ if ( err ) {
51+ return e ( 'svn not found' ) ;
52+ }
53+
54+ return c ( { path, version : parseVersion ( stdout . trim ( ) ) } ) ;
55+ } ) ;
56+ }
57+
58+ if ( path !== '/usr/bin/svn' ) {
59+ return getVersion ( path ) ;
60+ }
61+
62+ // must check if XCode is installed
63+ cp . exec ( 'xcode-select -p' , ( err : any ) => {
64+ if ( err && err . code === 2 ) {
65+ // svn is not installed, and launching /usr/bin/svn
66+ // will prompt the user to install it
67+
68+ return e ( 'svn not found' ) ;
69+ }
70+
71+ getVersion ( path ) ;
72+ } ) ;
73+ } ) ;
74+ } ) ;
75+ }
76+
77+ function findSystemSvnWin32 ( base : string ) : Promise < ISvn > {
78+ if ( ! base ) {
79+ return Promise . reject < ISvn > ( 'Not found' ) ;
80+ }
81+
82+ return findSpecificSvn ( path . join ( base , 'TortoiseSVN' , 'bin' , 'svn.exe' ) ) ;
83+ }
84+
85+ function findSvnWin32 ( ) : Promise < ISvn > {
86+ return findSystemSvnWin32 ( process . env [ 'ProgramW6432' ] )
87+ . then ( void 0 , ( ) => findSystemSvnWin32 ( process . env [ 'ProgramFiles(x86)' ] ) )
88+ . then ( void 0 , ( ) => findSystemSvnWin32 ( process . env [ 'ProgramFiles' ] ) )
89+ . then ( void 0 , ( ) => findSpecificSvn ( 'svn' ) ) ;
90+ }
91+
92+ export function findSvn ( hint : string | undefined ) : Promise < ISvn > {
93+ var first = hint ? findSpecificSvn ( hint ) : Promise . reject < ISvn > ( null ) ;
94+
95+ return first
96+ . then ( void 0 , ( ) => {
97+ switch ( process . platform ) {
98+ case 'darwin' : return findSvnDarwin ( ) ;
99+ case 'win32' : return findSvnWin32 ( ) ;
100+ default : return findSpecificSvn ( 'svn' ) ;
101+ }
102+ } )
103+ . then ( null , ( ) => Promise . reject ( new Error ( 'Svn installation not found.' ) ) ) ;
104+ }
105+
106+ export interface ISvnOptions {
107+ svnPath : string ;
108+ version : string ;
109+ }
110+
13111export class Svn {
112+ private svnPath : string ;
113+ private version : string ;
114+
14115 private _onOutput = new EventEmitter ( ) ;
15116 get onOutput ( ) : EventEmitter {
16117 return this . _onOutput ;
17118 }
18119
120+ constructor ( options : ISvnOptions ) {
121+ this . svnPath = options . svnPath ;
122+ this . version = options . version ;
123+ }
124+
19125 private log ( output : string ) : void {
20126 this . _onOutput . emit ( "log" , output ) ;
21127 }
@@ -29,7 +135,7 @@ export class Svn {
29135 this . log ( `svn ${ args . join ( " " ) } \n` ) ;
30136 }
31137
32- let process = cp . spawn ( "svn" , args , options ) ;
138+ let process = cp . spawn ( this . svnPath , args , options ) ;
33139
34140 let [ exitCode , stdout , stderr ] = await Promise . all < any > ( [
35141 new Promise < number > ( ( resolve , reject ) => {
0 commit comments