├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── index.js ├── package-lock.json ├── package.json └── test ├── commands.js └── createLocalSvnRepo.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /npm-debug.log 3 | /temp 4 | /api.md 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | node_js: 3 | - "node" 4 | cache: npm 5 | install: 6 | - npm install jshint -g 7 | - npm install 8 | script: 9 | - jshint index.js 10 | - npm test 11 | 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 peteward44 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-svn-ultimate 2 | 3 | ***This project is no longer maintained*** 4 | 5 | The ultimate SVN wrapper for node. Contains all the methods exposed by the command line svn tool, including checkout, update, info, etc, and includes svnmucc support. 6 | 7 | Has methods for manipulating both working copies and the repo directly. 8 | 9 | All direct svn command line functions are exposed through the commands object, and accept the same parameters as the command line tool. 10 | 11 | Utility methods are provided through a util object. 12 | 13 | ``` 14 | npm install node-svn-ultimate --save 15 | ``` 16 | 17 | ### Example usage 18 | 19 | ```js 20 | var svnUltimate = require('node-svn-ultimate'); 21 | 22 | svnUltimate.commands.checkout( 'https://my.url/svn/repo', '/home/user/checkout', function( err ) { 23 | console.log( "Checkout complete" ); 24 | } ); 25 | 26 | svnUltimate.commands.update( '/home/user/checkout', 27 | { // optional options object - can be passed to any command not just update 28 | trustServerCert: true, // same as --trust-server-cert 29 | username: "username", // same as --username 30 | password: "password", // same as --password 31 | shell: "sh", // override shell used to execute command 32 | cwd: process.cwd(), // override working directory command is executed 33 | quiet: true, // provide --quiet to commands that accept it 34 | force: true, // provide --force to commands that accept it 35 | revision: 33050, // provide --revision to commands that accept it 36 | depth: "empty", // provide --depth to commands that accept it 37 | ignoreExternals: true, // provide --ignore-externals to commands that accept it 38 | params: [ '-m "Commit comment"' ], // extra parameters to pass 39 | 'config-option': [ 40 | 'servers:global:http-proxy-host=proxy.someProxy.com', 41 | 'servers:global:http-proxy-port=8080', 42 | ] // provide --config-option to commands that accept it. Use an array for multiple config options 43 | }, 44 | function( err ) { 45 | console.log( "Update complete" ); 46 | } ); 47 | 48 | ``` 49 | 50 | ### Utility methods 51 | 52 | ```js 53 | // Gets the working copy revision or the HEAD revision if the target is a URL 54 | svnUltimate.util.getRevision( 'https://my.url/svn/repo', function( err, revision ) { 55 | console.log( "Head revision=" + revision ); 56 | } ); 57 | 58 | var obj = svnUltimate.util.parseUrl( 'https://my.url/svn/repo/trunk' ); 59 | // this call will return an object comprising of 60 | obj = { 61 | rootUrl: 'https://my.url/svn/repo', 62 | type: 'trunk', // either trunk, tags, or branches 63 | typeName: '1.3.5' // only populated if a tag or a branch, name of the tag or branch 64 | trunkUrl: 'https://my.url/svn/repo/trunk', 65 | tagsUrl: 'https://my.url/svn/repo/tags', 66 | branchesUrl: 'https://my.url/svn/repo/branches' 67 | }; 68 | 69 | 70 | svnUltimate.util.getTags( 'https://my.url/svn/repo/trunk', function( err, tagsArray ) { 71 | // tagsArray will be an array of strings containing all tag names 72 | } ); 73 | 74 | svnUltimate.util.getLatestTag( 'https://my.url/svn/repo/trunk', function( err, latestTag ) { 75 | // latestTag will be the most recent tag, worked out by semver comparison (not the date it was created) 76 | } ); 77 | 78 | ``` 79 | 80 | ## Methods 81 | 82 |
object
Exposes the commands for the command line svn tool.
85 |object
Exposes some custom utility methods
88 |object
93 |
94 | Exposes the commands for the command line svn tool.
95 |
96 | **Kind**: global namespace
97 |
98 | * [commands](#commands) : object
99 | * [.checkout(url, dir, [options], [callback])](#commands.checkout)
100 | * [.add(files, [options], [callback])](#commands.add)
101 | * [.cat(targets, [options], [callback])](#commands.cat)
102 | * [.cleanup(wc, [options], [callback])](#commands.cleanup)
103 | * [.commit(files, [options], [callback])](#commands.commit)
104 | * [.copy(srcs, dst, [options], [callback])](#commands.copy)
105 | * [.del(srcs, [options], [callback])](#commands.del)
106 | * [.export(src, dst, [options], [callback])](#commands.export)
107 | * [.import(src, dst, [options], [callback])](#commands.import)
108 | * [.info(targets, [options], [callback])](#commands.info)
109 | * [.list(targets, [options], [callback])](#commands.list)
110 | * [.lock(targets, [options], [callback])](#commands.lock)
111 | * [.log(targets, [options], [callback])](#commands.log)
112 | * [.merge(targets, [options], [callback])](#commands.merge)
113 | * [.mergeinfo(source, target, [options], [callback])](#commands.mergeinfo)
114 | * [.mkdir(targets, [options], [callback])](#commands.mkdir)
115 | * [.move(srcs, dst, [options], [callback])](#commands.move)
116 | * [.propdel(propName, target, [options], [callback])](#commands.propdel)
117 | * [.propget(propName, targets, [options], [callback])](#commands.propget)
118 | * [.proplist(targets, [options], [callback])](#commands.proplist)
119 | * [.propset(propName, propVal, wc, [options], [callback])](#commands.propset)
120 | * [.relocate(url, wc, [options], [callback])](#commands.relocate)
121 | * [.revert(wc, [options], [callback])](#commands.revert)
122 | * [.status(wc, [options], [callback])](#commands.status)
123 | * [.switch(url, wc, [options], [callback])](#commands.switch)
124 | * [.unlock(targets, [options], [callback])](#commands.unlock)
125 | * [.update(wcs, [options], [callback])](#commands.update)
126 | * [.upgrade(wcs, [options], [callback])](#commands.upgrade)
127 | * [.mucc(commandArray, commitMessage, [options], [callback])](#commands.mucc)
128 |
129 |
130 | ### commands.checkout(url, dir, [options], [callback])
131 | Checks out a repository to a working copy
132 |
133 | **Kind**: static method of [commands](#commands)
134 |
135 | | Param | Type | Description |
136 | | --- | --- | --- |
137 | | url | string
| Repository URL |
138 | | dir | string
| Working copy dir |
139 | | [options] | object
| Options object |
140 | | [callback] | function
| Complete callback |
141 |
142 |
143 | ### commands.add(files, [options], [callback])
144 | Adds a file / folder to a working copy
145 |
146 | **Kind**: static method of [commands](#commands)
147 |
148 | | Param | Type | Description |
149 | | --- | --- | --- |
150 | | files | Array
| string
| Add given files / folders |
151 | | [options] | object
| Options object |
152 | | [callback] | function
| Complete callback |
153 |
154 |
155 | ### commands.cat(targets, [options], [callback])
156 | Gets the content of a file from either a working copy or a URL.
157 |
158 | **Kind**: static method of [commands](#commands)
159 |
160 | | Param | Type | Description |
161 | | --- | --- | --- |
162 | | targets | Array
| string
| Array of URLs or working copy files to catalogue |
163 | | [options] | object
| Options object |
164 | | [callback] | function
| Complete callback |
165 |
166 |
167 | ### commands.cleanup(wc, [options], [callback])
168 | Performs an svn cleanup operation on the working copy
169 |
170 | **Kind**: static method of [commands](#commands)
171 |
172 | | Param | Type | Description |
173 | | --- | --- | --- |
174 | | wc | string
| Working copy directory to clean |
175 | | [options] | object
| Options object |
176 | | [callback] | function
| Complete callback |
177 |
178 |
179 | ### commands.commit(files, [options], [callback])
180 | Commits a working copy to a repository
181 |
182 | **Kind**: static method of [commands](#commands)
183 |
184 | | Param | Type | Description |
185 | | --- | --- | --- |
186 | | files | Array
| string
| Array of files / folders to commit |
187 | | [options] | object
| Options object |
188 | | [callback] | function
| Complete callback |
189 |
190 |
191 | ### commands.copy(srcs, dst, [options], [callback])
192 | Copies a file / folder within either a working copy or a URL
193 |
194 | **Kind**: static method of [commands](#commands)
195 |
196 | | Param | Type | Description |
197 | | --- | --- | --- |
198 | | srcs | Array
| string
| URLs / files to copy |
199 | | dst | string
| destination |
200 | | [options] | object
| Options object |
201 | | [callback] | function
| Complete callback |
202 |
203 |
204 | ### commands.del(srcs, [options], [callback])
205 | Deletes a file/folder from either a working copy or a URL
206 |
207 | **Kind**: static method of [commands](#commands)
208 |
209 | | Param | Type | Description |
210 | | --- | --- | --- |
211 | | srcs | Array
| string
| Array of URLs / files to delete |
212 | | [options] | object
| Options object |
213 | | [callback] | function
| Complete callback |
214 |
215 |
216 | ### commands.export(src, dst, [options], [callback])
217 | Exports a file from the repository to a local file
218 |
219 | **Kind**: static method of [commands](#commands)
220 |
221 | | Param | Type | Description |
222 | | --- | --- | --- |
223 | | src | string
| Source URL |
224 | | dst | string
| Destination file |
225 | | [options] | object
| Options object |
226 | | [callback] | function
| Complete callback |
227 |
228 |
229 | ### commands.import(src, dst, [options], [callback])
230 | Imports a file to the repository
231 |
232 | **Kind**: static method of [commands](#commands)
233 |
234 | | Param | Type | Description |
235 | | --- | --- | --- |
236 | | src | string
| Source file |
237 | | dst | string
| Destination URL |
238 | | [options] | object
| Options object |
239 | | [callback] | function
| Complete callback |
240 |
241 |
242 | ### commands.info(targets, [options], [callback])
243 | Performs an svn info command on a given working copy file / URL
244 |
245 | **Kind**: static method of [commands](#commands)
246 |
247 | | Param | Type | Description |
248 | | --- | --- | --- |
249 | | targets | Array
| string
| Target URLs / files to info |
250 | | [options] | object
| Options object |
251 | | [callback] | function
| Complete callback |
252 |
253 |
254 | ### commands.list(targets, [options], [callback])
255 | Lists the files within a directory, either working copy or URL
256 |
257 | **Kind**: static method of [commands](#commands)
258 |
259 | | Param | Type | Description |
260 | | --- | --- | --- |
261 | | targets | Array
| string
| Target URLs / files to list |
262 | | [options] | object
| Options object |
263 | | [callback] | function
| Complete callback |
264 |
265 |
266 | ### commands.lock(targets, [options], [callback])
267 | Locks a file in a working copy / repository
268 |
269 | **Kind**: static method of [commands](#commands)
270 |
271 | | Param | Type | Description |
272 | | --- | --- | --- |
273 | | targets | Array
| string
| Target URLs / files to lock |
274 | | [options] | object
| Options object |
275 | | [callback] | function
| Complete callback |
276 |
277 |
278 | ### commands.log(targets, [options], [callback])
279 | Gets the SVN message log and returns as a JSON object
280 |
281 | **Kind**: static method of [commands](#commands)
282 |
283 | | Param | Type | Description |
284 | | --- | --- | --- |
285 | | targets | Array
| string
| Target URLs / files to get logs for |
286 | | [options] | object
| Options object |
287 | | [callback] | function
| Complete callback |
288 |
289 |
290 | ### commands.merge(targets, [options], [callback])
291 | Apply the differences between two sources to a working copy path
292 |
293 | **Kind**: static method of [commands](#commands)
294 |
295 | | Param | Type | Description |
296 | | --- | --- | --- |
297 | | targets | Array
| string
| Target URLs |
298 | | [options] | object
| Options object |
299 | | [callback] | function
| Complete callback |
300 |
301 |
302 |
303 | ### commands.mergeinfo(source, target, [options], [callback])
304 | Query information related to merges (or potential merges) between SOURCE and TARGET.
305 |
306 | **Kind**: static method of [commands
](#commands)
307 |
308 | | Param | Type | Description |
309 | | --- | --- | --- |
310 | | source | string
| SOURCE URL |
311 | | target | string
| TARGET URL |
312 | | [options] | object
| Options object |
313 | | [callback] | function
| Complete callback |
314 |
315 |
316 | ### commands.mkdir(targets, [options], [callback])
317 | Creates a directory in the working copy or repository
318 |
319 | **Kind**: static method of [commands](#commands)
320 |
321 | | Param | Type | Description |
322 | | --- | --- | --- |
323 | | targets | Array
| string
| Target URLs / folders to create |
324 | | [options] | object
| Options object |
325 | | [callback] | function
| Complete callback |
326 |
327 |
328 | ### commands.move(srcs, dst, [options], [callback])
329 | Moves a file / folder in a working copy or URL
330 |
331 | **Kind**: static method of [commands](#commands)
332 |
333 | | Param | Type | Description |
334 | | --- | --- | --- |
335 | | srcs | Array
| string
| Target URLs / files to move |
336 | | dst | string
| Destination URL / file |
337 | | [options] | object
| Options object |
338 | | [callback] | function
| Complete callback |
339 |
340 |
341 | ### commands.propdel(propName, target, [options], [callback])
342 | Deletes an svn property from a working copy / repository
343 |
344 | **Kind**: static method of [commands](#commands)
345 |
346 | | Param | Type | Description |
347 | | --- | --- | --- |
348 | | propName | string
| Property name |
349 | | target | string
| Target file / folder or URL |
350 | | [options] | object
| Options object |
351 | | [callback] | function
| Complete callback |
352 |
353 |
354 | ### commands.propget(propName, targets, [options], [callback])
355 | Gets an svn property from a working copy / repository
356 |
357 | **Kind**: static method of [commands](#commands)
358 |
359 | | Param | Type | Description |
360 | | --- | --- | --- |
361 | | propName | string
| Property name |
362 | | targets | Array
| string
| Target file / folder or URL |
363 | | [options] | object
| Options object |
364 | | [callback] | function
| Complete callback |
365 |
366 |
367 | ### commands.proplist(targets, [options], [callback])
368 | Lists svn properties from a working copy / repository
369 |
370 | **Kind**: static method of [commands](#commands)
371 |
372 | | Param | Type | Description |
373 | | --- | --- | --- |
374 | | targets | Array
| string
| Target file / folder or URL |
375 | | [options] | object
| Options object |
376 | | [callback] | function
| Complete callback |
377 |
378 |
379 | ### commands.propset(propName, propVal, wc, [options], [callback])
380 | Sets an svn property from a working copy / repository
381 |
382 | **Kind**: static method of [commands](#commands)
383 |
384 | | Param | Type | Description |
385 | | --- | --- | --- |
386 | | propName | string
| Property name |
387 | | propVal | string
| Property value |
388 | | wc | string
| Target file / folder or URL |
389 | | [options] | object
| Options object |
390 | | [callback] | function
| Complete callback |
391 |
392 |
393 | ### commands.relocate(url, wc, [options], [callback])
394 | Relocates an svn working copy
395 |
396 | **Kind**: static method of [commands](#commands)
397 |
398 | | Param | Type | Description |
399 | | --- | --- | --- |
400 | | url | string
| Relocation URL |
401 | | wc | string
| Working copy to relocate |
402 | | [options] | object
| Options object |
403 | | [callback] | function
| Complete callback |
404 |
405 |
406 | ### commands.revert(wc, [options], [callback])
407 | Reverts files / folders in a working copy to their uncommited state
408 |
409 | **Kind**: static method of [commands](#commands)
410 |
411 | | Param | Type | Description |
412 | | --- | --- | --- |
413 | | wc | string
| Working copy target |
414 | | [options] | object
| Options object |
415 | | [callback] | function
| Complete callback |
416 |
417 |
418 | ### commands.status(wc, [options], [callback])
419 | Performs an svn status command on a working copy
420 |
421 | **Kind**: static method of [commands](#commands)
422 |
423 | | Param | Type | Description |
424 | | --- | --- | --- |
425 | | wc | string
| Working copy target |
426 | | [options] | object
| Options object |
427 | | [callback] | function
| Complete callback |
428 |
429 |
430 | ### commands.switch(url, wc, [options], [callback])
431 | Switches to a given branch / tag for a working copy
432 |
433 | **Kind**: static method of [commands](#commands)
434 |
435 | | Param | Type | Description |
436 | | --- | --- | --- |
437 | | url | string
| Switch URL |
438 | | wc | string
| Working copy target |
439 | | [options] | object
| Options object |
440 | | [callback] | function
| Complete callback |
441 |
442 |
443 | ### commands.unlock(targets, [options], [callback])
444 | Unlocks a previously locked svn file from a working copy / repository
445 |
446 | **Kind**: static method of [commands](#commands)
447 |
448 | | Param | Type | Description |
449 | | --- | --- | --- |
450 | | targets | Array
| string
| Working copy / URL targets |
451 | | [options] | object
| Options object |
452 | | [callback] | function
| Complete callback |
453 |
454 |
455 | ### commands.update(wcs, [options], [callback])
456 | Updates an svn working copy
457 |
458 | **Kind**: static method of [commands](#commands)
459 |
460 | | Param | Type | Description |
461 | | --- | --- | --- |
462 | | wcs | Array
| string
| Working copy targets |
463 | | [options] | object
| Options object |
464 | | [callback] | function
| Complete callback |
465 |
466 |
467 | ### commands.upgrade(wcs, [options], [callback])
468 | Upgrades a given svn working copy (requires v1.7 of svn client)
469 |
470 | **Kind**: static method of [commands](#commands)
471 |
472 | | Param | Type | Description |
473 | | --- | --- | --- |
474 | | wcs | Array
| string
| Working copy targets |
475 | | [options] | object
| Options object |
476 | | [callback] | function
| Complete callback |
477 |
478 |
479 | ### commands.mucc(commandArray, commitMessage, [options], [callback])
480 | Executes svnmucc command, for multiple commands
481 |
482 | **Kind**: static method of [commands](#commands)
483 | **See**: http://svnbook.red-bean.com/en/1.8/svn.ref.svnmucc.re.html
484 |
485 | | Param | Type | Description |
486 | | --- | --- | --- |
487 | | commandArray | Array
| Array of command strings, see above link for options |
488 | | commitMessage | string
| Commit message to use |
489 | | [options] | object
| Options object |
490 | | [callback] | function
| Complete callback |
491 |
492 |
493 | ## util : object
494 | Exposes some custom utility methods
495 |
496 | **Kind**: global namespace
497 |
498 | * [util](#util) : object
499 | * [.getRevision(target, [options], [callback])](#util.getRevision)
500 | * [.getWorkingCopyRevision(wcDir, [options], [callback])](#util.getWorkingCopyRevision)
501 | * [.parseUrl(url)](#util.parseUrl) ? object
502 | * [.getTags(url, [options], [callback])](#util.getTags)
503 | * [.getLatestTag(url, options, [callback])](#util.getLatestTag)
504 |
505 |
506 | ### util.getRevision(target, [options], [callback])
507 | Gets head revision of a given URL
508 |
509 | **Kind**: static method of [util](#util)
510 |
511 | | Param | Type | Description |
512 | | --- | --- | --- |
513 | | target | string
| Target URL |
514 | | [options] | object
| Options object |
515 | | [callback] | function
| Complete callback |
516 |
517 |
518 | ### util.getWorkingCopyRevision(wcDir, [options], [callback])
519 | Gets the revision of a working copy.
520 |
521 | **Kind**: static method of [util](#util)
522 |
523 | | Param | Type | Description |
524 | | --- | --- | --- |
525 | | wcDir | string
| Working copy folder |
526 | | [options] | object
| Options object |
527 | | [callback] | function
| Complete callback |
528 |
529 |
530 | ### util.parseUrl(url) ? object
531 | Parse a url for an SVN project repository and breaks it apart
532 |
533 | **Kind**: static method of [util](#util)
534 |
535 | | Param | Type | Description |
536 | | --- | --- | --- |
537 | | url | string
| URL to parse |
538 |
539 |
540 | ### util.getTags(url, [options], [callback])
541 | Gets all available tags for the given svn URL
542 |
543 | **Kind**: static method of [util](#util)
544 |
545 | | Param | Type | Description |
546 | | --- | --- | --- |
547 | | url | string
| Project URL to get tags for |
548 | | [options] | object
| Options object |
549 | | [callback] | function
| Complete callback |
550 |
551 |
552 | ### util.getLatestTag(url, options, [callback])
553 | Uses node's semver package to work out the latest tag value
554 |
555 | **Kind**: static method of [util](#util)
556 |
557 | | Param | Type | Description |
558 | | --- | --- | --- |
559 | | url | string
| Project URL to get latest tag for |
560 | | options | object
| Options object |
561 | | [callback] | function
| Complete callback |
562 |
563 |
564 | ### util.getBranches(url, [options], [callback])
565 | Gets all available branches for the given svn URL
566 |
567 | **Kind**: static method of [util](#util)
568 |
569 | | Param | Type | Description |
570 | | --- | --- | --- |
571 | | url | string
| Project URL to get branches for |
572 | | [options] | object
| Options object |
573 | | [callback] | function
| Complete callback |
574 |
575 |
576 |
577 |
578 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*jslint node: true */
2 | 'use strict';
3 |
4 | var exec = require( 'child_process' ).exec;
5 | var fs = require( 'fs-extra' );
6 | var os = require( 'os' );
7 | var path = require( 'path' );
8 | var uuid = require( 'uuid' );
9 | var xml2js = require( 'xml2js' );
10 | var semver = require( 'semver' );
11 |
12 |
13 |
14 | var xmlToJson = function( dataXml, callback ) {
15 | xml2js.parseString(dataXml,
16 | {
17 | explicitRoot: false,
18 | explicitArray: false
19 | },
20 | function( err, json ) { callback( err, json ); }
21 | );
22 | };
23 |
24 | var execute = function( cmd, options, callback ) {
25 |
26 | options = options || {};
27 | if ( options.shell === undefined && os.platform === "win32" ) {
28 | options.shell = 'start "" /B '; // windows only - this makes it so a cmd window won't pop up when running as a service or through pm2
29 | }
30 | options.cwd = options.cwd || process.cwd();
31 | var execOptions = {
32 | cwd: options.cwd,
33 | shell: options.shell,
34 | maxBuffer: options.maxBuffer || ( 5 * 1024 * 1024 ) // defaults to 5MB
35 | };
36 |
37 | if ( !options.noStandardOptions ) {
38 | cmd += ' --non-interactive';
39 | if ( options.trustServerCert ) {
40 | cmd += ' --trust-server-cert';
41 | }
42 | if ( typeof options.username === 'string' ) {
43 | cmd += ' --username=' + options.username;
44 | }
45 | if ( typeof options.password === 'string' ) {
46 | cmd += ' --password=' + options.password;
47 | }
48 | if ( options['config-option'] ) {
49 | if ( Array.isArray(options['config-option']) ) {
50 | options['config-option'].forEach( function( option ) {
51 | cmd += ' --config-option=' + option;
52 | });
53 | } else {
54 | cmd += ' --config-option=' + options['config-option'];
55 | }
56 | }
57 | }
58 | if ( options.params ) {
59 | cmd += ' ' + options.params.join( " " );
60 | }
61 | exec( cmd, execOptions, function( err, stdo, stde ) {
62 | if ( !options.quiet ) {
63 | process.stderr.write( stde.toString() );
64 | }
65 | if ( typeof callback === 'function' ) {
66 | callback( err, options.stdoutAsBuffer ? stdo : stdo.toString() );
67 | }
68 | } );
69 | };
70 |
71 |
72 | var executeSvn = function( params, options, callback ) {
73 | options = options || {};
74 | var cmd = ( options.svn || 'svn' ) + ' ' + params.join( " " );
75 | execute( cmd, options, callback );
76 | };
77 |
78 |
79 | var executeSvnXml = function( params, options, callback ) {
80 | executeSvn( params.concat( [ '--xml' ] ), options, function( err, data ) {
81 | if ( !err ) {
82 | xmlToJson( data, function( err2, json ) {
83 | callback( err2, json );
84 | } );
85 | } else {
86 | callback( err, null );
87 | }
88 | } );
89 | };
90 |
91 |
92 | var executeMucc = function( params, options, callback ) {
93 | options = options || {};
94 | var cmd = ( options.svnmucc || 'svnmucc' ) + ' ' + params.join( " " );
95 | execute( cmd, options, callback );
96 | };
97 |
98 |
99 | var execSvnVersion = function( params, options, callback ) {
100 | options = options || {};
101 | var cmd = ( options.svnversion || 'svnversion' ) + ' ' + params.join( " " );
102 | options.noStandardOptions = true;
103 | execute( cmd, options, callback );
104 | };
105 |
106 |
107 | var checkSvnVersion = function( options, reqVersion, callback ) {
108 | options = options || {};
109 | options.noStandardOptions = true;
110 | var cmd = ( options.svn || 'svn' ) + ' --version --quiet';
111 | execute( cmd, options, function( err, stdo ) {
112 | if ( err ) {
113 | return callback( err );
114 | }
115 | stdo = stdo.trim();
116 | callback( null, semver.satisfies( stdo, reqVersion ) );
117 | } );
118 | };
119 |
120 |
121 | var addExtraOptions = function( validOptionsArray, options, addRevProp ) {
122 | if ( options ) {
123 | options.params = options.params || [];
124 | validOptionsArray.forEach( function( validOption ) {
125 | switch ( validOption ) {
126 | case 'force':
127 | if ( options.force ) {
128 | options.params.push('--force');
129 | }
130 | break;
131 | case 'quiet':
132 | if ( options.quiet ) {
133 | options.params.push('--quiet');
134 | }
135 | break;
136 | case 'revision':
137 | if ( options.revision ) {
138 | options.params.push('--revision', options.revision.toString());
139 | if ( addRevProp ) {
140 | options.params.push( '--revprop' );
141 | }
142 | }
143 | break;
144 | case 'depth':
145 | if ( options.depth ) {
146 | options.params.push('--depth', options.depth.toString());
147 | }
148 | break;
149 | case 'ignoreExternals':
150 | if ( options.ignoreExternals ) {
151 | options.params.push('--ignore-externals');
152 | }
153 | break;
154 | case 'msg':
155 | if ( options.msg ) {
156 | options.params.push('-m', '"' + options.msg + '"');
157 | }
158 | break;
159 | case 'verbose':
160 | if ( options.verbose ) {
161 | options.params.push('--verbose');
162 | }
163 | break;
164 | case 'showRevs':
165 | if ( options.showRevs ) {
166 | options.params.push('--show-revs', options.showRevs);
167 | }
168 | break;
169 | case 'limit':
170 | if ( options.limit ) {
171 | options.params.push('--limit', options.limit.toString());
172 | }
173 | break;
174 | }
175 | } );
176 | }
177 | return options;
178 | };
179 |
180 | /** Exposes the commands for the command line svn tool.
181 | * @namespace commands
182 | */
183 | exports.commands = {};
184 |
185 |
186 | /** Checks out a repository to a working copy
187 | * @function checkout
188 | * @memberof commands
189 | * @param {string} url - Repository URL
190 | * @param {string} dir - Working copy dir
191 | * @param {object} [options] - Options object
192 | * @param {function} [callback] - Complete callback
193 | * @alias co
194 | */
195 | var checkout = function( url, dir, options, callback ) {
196 | if ( typeof options === 'function' ) {
197 | callback = options;
198 | options = null;
199 | }
200 | options = options || {};
201 | addExtraOptions( [ 'force', 'quiet', 'revision', 'depth', 'ignoreExternals' ], options );
202 |
203 | var dirPath = dir;
204 | if(typeof options.cwd !== 'undefined')
205 | dirPath = path.resolve(options.cwd, dir);
206 | if ( !fs.existsSync( dirPath ) ) {
207 | fs.mkdirsSync( dirPath );
208 | }
209 | executeSvn( [ 'checkout', url, dir ], options, callback );
210 | };
211 | exports.commands.checkout = checkout;
212 | exports.commands.co = checkout;
213 |
214 | /** Adds a file / folder to a working copy
215 | * @function add
216 | * @memberof commands
217 | * @param {Array|string} files - Add given files / folders
218 | * @param {object} [options] - Options object
219 | * @param {function} [callback] - Complete callback
220 | */
221 | var add = function( files, options, callback ) {
222 | if ( !Array.isArray( files ) ) {
223 | files = [files];
224 | }
225 | if ( typeof options === 'function' ) {
226 | callback = options;
227 | options = null;
228 | }
229 | options = options || {};
230 | addExtraOptions( [ 'force', 'quiet', 'depth' ], options );
231 | executeSvn( [ 'add' ].concat( files ), options, callback );
232 | };
233 | exports.commands.add = add;
234 |
235 | // TODO: blame
236 |
237 | /** Gets the content of a file from either a working copy or a URL.
238 | * @function cat
239 | * @memberof commands
240 | * @param {Array|string} targets - Array of URLs or working copy files to catalogue
241 | * @param {object} [options] - Options object
242 | * @param {function} [callback] - Complete callback
243 | */
244 | var cat = function( targets, options, callback ) {
245 | if ( !Array.isArray( targets ) ) {
246 | targets = [targets];
247 | }
248 | if ( typeof options === 'function' ) {
249 | callback = options;
250 | options = null;
251 | }
252 | options = options || {};
253 | addExtraOptions( [ 'revision' ], options );
254 | executeSvn( [ 'cat' ].concat( targets ), options, callback );
255 | };
256 | exports.commands.cat = cat;
257 |
258 | // TODO: changelist (cl)
259 |
260 | /** Performs an svn cleanup operation on the working copy
261 | * @function cleanup
262 | * @memberof commands
263 | * @param {string} wc - Working copy directory to clean
264 | * @param {object} [options] - Options object
265 | * @param {function} [callback] - Complete callback
266 | */
267 | var cleanup = function( wc, options, callback ) {
268 | if ( typeof options === 'function' ) {
269 | callback = options;
270 | options = null;
271 | }
272 | options = options || {};
273 | executeSvn( [ 'cleanup', wc ], options, callback );
274 | };
275 | exports.commands.cleanup = cleanup;
276 |
277 | /** Commits a working copy to a repository
278 | * @function commit
279 | * @memberof commands
280 | * @param {Array|string} files - Array of files / folders to commit
281 | * @param {object} [options] - Options object
282 | * @param {function} [callback] - Complete callback
283 | * @alias ci
284 | */
285 | var commit = function( files, options, callback ) {
286 | if ( !Array.isArray( files ) ) {
287 | files = [files];
288 | }
289 | if ( typeof options === 'function' ) {
290 | callback = options;
291 | options = null;
292 | } else if ( typeof options === 'string' ) {
293 | options = { msg: options };
294 | }
295 | options = options || {};
296 | addExtraOptions( [ 'quiet', 'depth', 'msg' ], options );
297 | executeSvn( [ 'commit' ].concat( files ), options, callback );
298 | };
299 | exports.commands.commit = commit;
300 | exports.commands.ci = commit;
301 |
302 | /** Copies a file / folder within either a working copy or a URL
303 | * @function copy
304 | * @memberof commands
305 | * @param {Array|string} srcs - URLs / files to copy
306 | * @param {string} dst - destination
307 | * @param {object} [options] - Options object
308 | * @param {function} [callback] - Complete callback
309 | * @alias cp
310 | */
311 | var copy = function( srcs, dst, options, callback ) {
312 | if ( !Array.isArray( srcs ) ) {
313 | srcs = [srcs];
314 | }
315 | if ( typeof options === 'function' ) {
316 | callback = options;
317 | options = null;
318 | } else if ( typeof options === 'string' ) {
319 | options = { msg: options };
320 | }
321 | options = options || {};
322 | addExtraOptions( [ 'revision', 'quiet', 'depth', 'msg' ], options );
323 | executeSvn( [ 'copy' ].concat( srcs ).concat( [ dst ] ), options, callback );
324 | };
325 | exports.commands.copy = copy;
326 | exports.commands.cp = copy;
327 |
328 | /** Deletes a file/folder from either a working copy or a URL
329 | * @function del
330 | * @memberof commands
331 | * @param {Array|string} srcs - Array of URLs / files to delete
332 | * @param {object} [options] - Options object
333 | * @param {function} [callback] - Complete callback
334 | * @alias remove
335 | * @alias rm
336 | */
337 | var del = function( srcs, options, callback ) {
338 | if ( !Array.isArray( srcs ) ) {
339 | srcs = [srcs];
340 | }
341 | if ( typeof options === 'function' ) {
342 | callback = options;
343 | options = null;
344 | } else if ( typeof options === 'string' ) {
345 | options = { msg: options };
346 | }
347 | options = options || {};
348 | addExtraOptions( [ 'quiet', 'force', 'msg' ], options );
349 | executeSvn( [ 'del' ].concat( srcs ), options, callback );
350 | };
351 | exports.commands.del = del;
352 | exports.commands.remove = del;
353 | exports.commands.rm = del;
354 |
355 | // var diff = function( src, dest, options, callback ) {
356 | // if ( typeof options === 'function' ) {
357 | // callback = options;
358 | // options = null;
359 | // }
360 | // options = options || {};
361 | // addExtraOptions( [ 'revision', 'depth', 'force' ], options );
362 | // executeSvn( [ 'export', src, dst ], options, callback );
363 | // };
364 | // exports.commands.diff = diff;
365 |
366 |
367 | /** Exports a file from the repository to a local file
368 | * @function export
369 | * @memberof commands
370 | * @param {string} src - Source URL
371 | * @param {string} dst - Destination file
372 | * @param {object} [options] - Options object
373 | * @param {function} [callback] - Complete callback
374 | * @alias exp
375 | */
376 | var exp = function( src, dst, options, callback ) {
377 | if ( typeof options === 'function' ) {
378 | callback = options;
379 | options = null;
380 | }
381 | options = options || {};
382 | addExtraOptions( [ 'revision', 'quiet', 'force' ], options );
383 | executeSvn( [ 'export', src, dst ], options, callback );
384 | };
385 | exports.commands.export = exp;
386 | exports.commands.exp = exp;
387 |
388 | /** Imports a file to the repository
389 | * @function import
390 | * @memberof commands
391 | * @param {string} src - Source file
392 | * @param {string} dst - Destination URL
393 | * @param {object} [options] - Options object
394 | * @param {function} [callback] - Complete callback
395 | * @alias imp
396 | */
397 | var imp = function( src, dst, options, callback ) {
398 | if ( typeof options === 'function' ) {
399 | callback = options;
400 | options = null;
401 | } else if ( typeof options === 'string' ) {
402 | options = { msg: options };
403 | }
404 | options = options || {};
405 | addExtraOptions( [ 'depth', 'quiet', 'force', 'msg' ], options );
406 | executeSvn( [ 'import', src, dst ], options, callback );
407 | };
408 | exports.commands.import = imp;
409 | exports.commands.imp = imp;
410 |
411 | /** Performs an svn info command on a given working copy file / URL
412 | * @function info
413 | * @memberof commands
414 | * @param {Array|string} targets - Target URLs / files to info
415 | * @param {object} [options] - Options object
416 | * @param {function} [callback] - Complete callback
417 | */
418 | var info = function( targets, options, callback ) {
419 | if ( !Array.isArray( targets ) ) {
420 | targets = [targets];
421 | }
422 | if ( typeof options === 'function' ) {
423 | callback = options;
424 | options = null;
425 | }
426 | options = options || {};
427 | addExtraOptions( [ 'depth', 'revision' ], options );
428 | executeSvnXml( [ 'info' ].concat( targets ), options, callback );
429 | };
430 | exports.commands.info = info;
431 |
432 | /** Lists the files within a directory, either working copy or URL
433 | * @function list
434 | * @memberof commands
435 | * @param {Array|string} targets - Target URLs / files to list
436 | * @param {object} [options] - Options object
437 | * @param {function} [callback] - Complete callback
438 | * @alias ls
439 | */
440 | var list = function( targets, options, callback ) {
441 | if ( !Array.isArray( targets ) ) {
442 | targets = [targets];
443 | }
444 | if ( typeof options === 'function' ) {
445 | callback = options;
446 | options = null;
447 | }
448 | options = options || {};
449 | addExtraOptions( [ 'depth', 'revision' ], options );
450 | executeSvnXml( [ 'list' ].concat( targets ), options, callback );
451 | };
452 | exports.commands.list = list;
453 | exports.commands.ls = list;
454 |
455 | /** Locks a file in a working copy / repository
456 | * @function lock
457 | * @memberof commands
458 | * @param {Array|string} targets - Target URLs / files to lock
459 | * @param {object} [options] - Options object
460 | * @param {function} [callback] - Complete callback
461 | */
462 | var lock = function( targets, options, callback ) {
463 | if ( !Array.isArray( targets ) ) {
464 | targets = [targets];
465 | }
466 | if ( typeof options === 'function' ) {
467 | callback = options;
468 | options = null;
469 | } else if ( typeof options === 'string' ) {
470 | options = { msg: options };
471 | }
472 | options = options || {};
473 | addExtraOptions( [ 'force', 'msg' ], options );
474 | executeSvn( [ 'lock' ].concat( targets ), options, callback );
475 | };
476 | exports.commands.lock = lock;
477 |
478 | /** Gets the SVN message log and returns as a JSON object
479 | * @function log
480 | * @memberof commands
481 | * @param {Array|string} targets - Target URLs / files to get logs for
482 | * @param {object} [options] - Options object
483 | * @param {function} [callback] - Complete callback
484 | */
485 | var log = function( targets, options, callback ) {
486 | if ( !Array.isArray( targets ) ) {
487 | targets = [targets];
488 | }
489 | if ( typeof options === 'function' ) {
490 | callback = options;
491 | options = null;
492 | }
493 | options = options || {};
494 | addExtraOptions( [ 'quiet', 'depth', 'revision', 'verbose','limit' ], options );
495 | executeSvnXml( [ 'log' ].concat( targets ), options, callback );
496 | };
497 | exports.commands.log = log;
498 |
499 |
500 | /** Apply the differences between two sources to a working copy path.
501 | * @function merge
502 | * @memberof commands
503 | * @param {Array|string} targets - Target URLs
504 | * @param {object} [options] - Options object
505 | * @param {function} [callback] - Complete callback
506 | */
507 | var merge = function( targets, options, callback ) {
508 | if ( !Array.isArray( targets ) ) {
509 | targets = [targets];
510 | }
511 | if ( typeof options === 'function' ) {
512 | callback = options;
513 | options = null;
514 | }
515 | options = options || {};
516 | addExtraOptions( [ 'force', 'quiet', 'revision', 'depth' ], options );
517 | executeSvn( [ 'merge' ].concat( targets ), options, callback );
518 | };
519 | exports.commands.merge = merge;
520 |
521 | /** Query information related to merges (or potential merges) between SOURCE and TARGET.
522 | * @function mergeinfo
523 | * @memberof commands
524 | * @param {string} source - SOURCE URL
525 | * @param {string} target - TARGET URL
526 | * @param {object} [options] - Options object
527 | * @param {function} [callback] - Complete callback
528 | */
529 | var mergeinfo = function( source, target, options, callback ) {
530 | if ( typeof options === 'function' ) {
531 | callback = options;
532 | options = null;
533 | }
534 | options = options || {};
535 | addExtraOptions( [ 'quiet', 'msg', 'verbose', 'log', 'showRevs' ], options );
536 | executeSvn( [ 'mergeinfo' ].concat( source ).concat( target ), options, callback );
537 | };
538 | exports.commands.mergeinfo = mergeinfo;
539 |
540 | /** Creates a directory in the working copy or repository
541 | * @function mkdir
542 | * @memberof commands
543 | * @param {Array|string} targets - Target URLs / folders to create
544 | * @param {object} [options] - Options object
545 | * @param {function} [callback] - Complete callback
546 | */
547 | var mkdir = function( targets, options, callback ) {
548 | if ( !Array.isArray( targets ) ) {
549 | targets = [targets];
550 | }
551 | if ( typeof options === 'function' ) {
552 | callback = options;
553 | options = null;
554 | } else if ( typeof options === 'string' ) {
555 | options = { msg: options };
556 | }
557 | options = options || {};
558 | addExtraOptions( [ 'quiet', 'msg' ], options );
559 | executeSvn( [ 'mkdir' ].concat( targets ), options, callback );
560 | };
561 | exports.commands.mkdir = mkdir;
562 |
563 | /** Moves a file / folder in a working copy or URL
564 | * @function move
565 | * @memberof commands
566 | * @param {Array|string} srcs - Target URLs / files to move
567 | * @param {string} dst - Destination URL / file
568 | * @param {object} [options] - Options object
569 | * @param {function} [callback] - Complete callback
570 | * @alias mv
571 | * @alias rename
572 | * @alias ren
573 | */
574 | var move = function( srcs, dst, options, callback ) {
575 | if ( !Array.isArray( srcs ) ) {
576 | srcs = [srcs];
577 | }
578 | if ( typeof options === 'function' ) {
579 | callback = options;
580 | options = null;
581 | } else if ( typeof options === 'string' ) {
582 | options = { msg: options };
583 | }
584 | options = options || {};
585 | addExtraOptions( [ 'quiet', 'force', 'msg' ], options );
586 | executeSvn( [ 'move' ].concat( srcs ).concat( [ dst ] ), options, callback );
587 | };
588 | exports.commands.move = move;
589 | exports.commands.mv = move;
590 | exports.commands.rename = move;
591 | exports.commands.ren = move;
592 |
593 | // var patch = function( patchFile, wc, options, callback ) {
594 | // if ( typeof options === 'function' ) {
595 | // callback = options;
596 | // options = null;
597 | // }
598 | // options = options || {};
599 | // executeSvn( [ 'patch', patchFile, wc ], options, callback );
600 | // };
601 | // exports.commands.patch = patch;
602 |
603 | /** Deletes an svn property from a working copy / repository
604 | * @function propdel
605 | * @memberof commands
606 | * @param {string} propName - Property name
607 | * @param {string} target - Target file / folder or URL
608 | * @param {object} [options] - Options object
609 | * @param {function} [callback] - Complete callback
610 | * @alias pdel
611 | * @alias pd
612 | */
613 | var propdel = function( propName, target, options, callback ) {
614 | if ( typeof options === 'function' ) {
615 | callback = options;
616 | options = null;
617 | }
618 | options = options || {};
619 | addExtraOptions( [ 'quiet', 'depth' ], options, true );
620 | executeSvn( [ 'propdel', propName, target ], options, callback );
621 | };
622 | exports.commands.propdel = propdel;
623 | exports.commands.pdel = propdel;
624 | exports.commands.pd = propdel;
625 |
626 | // propedit (pedit, pe) - not supported
627 |
628 | /** Gets an svn property from a working copy / repository
629 | * @function propget
630 | * @memberof commands
631 | * @param {string} propName - Property name
632 | * @param {Array|string} targets - Target file / folder or URL
633 | * @param {object} [options] - Options object
634 | * @param {function} [callback] - Complete callback
635 | * @alias pget
636 | * @alias pg
637 | */
638 | var propget = function( propName, targets, options, callback ) {
639 | if ( typeof options === 'function' ) {
640 | callback = options;
641 | options = null;
642 | }
643 | if ( !Array.isArray( targets ) ) {
644 | targets = [targets];
645 | }
646 | options = options || {};
647 | addExtraOptions( [ 'depth', 'revision' ], options, true );
648 | executeSvnXml( [ 'propget', propName ].concat( targets ), options, callback );
649 | };
650 | exports.commands.propget = propget;
651 | exports.commands.pget = propget;
652 | exports.commands.pg = propget;
653 |
654 | /** Lists svn properties from a working copy / repository
655 | * @function proplist
656 | * @memberof commands
657 | * @param {Array|string} targets - Target file / folder or URL
658 | * @param {object} [options] - Options object
659 | * @param {function} [callback] - Complete callback
660 | * @alias plist
661 | * @alias pl
662 | */
663 | var proplist = function( targets, options, callback ) {
664 | if ( typeof options === 'function' ) {
665 | callback = options;
666 | options = null;
667 | }
668 | if ( !Array.isArray( targets ) ) {
669 | targets = [targets];
670 | }
671 | options = options || {};
672 | addExtraOptions( [ 'quiet', 'depth', 'revision' ], options, true );
673 | executeSvnXml( [ 'proplist' ].concat( targets ), options, callback );
674 | };
675 | exports.commands.proplist = proplist;
676 | exports.commands.plist = proplist;
677 | exports.commands.pl = proplist;
678 |
679 | /** Sets an svn property from a working copy / repository
680 | * @function propset
681 | * @memberof commands
682 | * @param {string} propName - Property name
683 | * @param {string} propVal - Property value
684 | * @param {string} wc - Target file / folder or URL
685 | * @param {object} [options] - Options object
686 | * @param {function} [callback] - Complete callback
687 | * @alias pset
688 | * @alias ps
689 | */
690 | var propset = function( propName, propVal, wc, options, callback ) {
691 | if ( typeof options === 'function' ) {
692 | callback = options;
693 | options = null;
694 | }
695 | options = options || {};
696 | addExtraOptions( [ 'quiet', 'depth', 'revision', 'force' ], options, true );
697 | executeSvn( [ 'propset', propName, propVal, wc ], options, callback );
698 | };
699 | exports.commands.propset = propset;
700 | exports.commands.pset = propset;
701 | exports.commands.ps = propset;
702 |
703 | /** Relocates an svn working copy
704 | * @function relocate
705 | * @memberof commands
706 | * @param {string} url - Relocation URL
707 | * @param {string} wc - Working copy to relocate
708 | * @param {object} [options] - Options object
709 | * @param {function} [callback] - Complete callback
710 | */
711 | var relocate = function( url, wc, options, callback ) {
712 | if ( typeof options === 'function' ) {
713 | callback = options;
714 | options = null;
715 | }
716 | options = options || {};
717 | executeSvn( [ 'relocate', url, wc ], options, callback );
718 | };
719 | exports.commands.relocate = relocate;
720 |
721 | // resolve/resolved - probably doesn't make sense to automate
722 |
723 | /** Reverts files / folders in a working copy to their uncommited state
724 | * @function revert
725 | * @memberof commands
726 | * @param {string} wc - Working copy target
727 | * @param {object} [options] - Options object
728 | * @param {function} [callback] - Complete callback
729 | */
730 | var revert = function( wc, options, callback ) {
731 | if ( typeof options === 'function' ) {
732 | callback = options;
733 | options = null;
734 | }
735 | options = options || {};
736 | addExtraOptions( [ 'quiet', 'depth' ], options );
737 | if ( !Array.isArray( wc ) ) {
738 | wc = [wc];
739 | }
740 | executeSvn( [ 'revert' ].concat( wc ), options, callback );
741 | };
742 | exports.commands.revert = revert;
743 |
744 | /** Performs an svn status command on a working copy
745 | * @function status
746 | * @memberof commands
747 | * @param {string} wc - Working copy target
748 | * @param {object} [options] - Options object
749 | * @param {function} [callback] - Complete callback
750 | * @alias stat
751 | * @alias st
752 | */
753 | var status = function( wc, options, callback ) {
754 | if ( typeof options === 'function' ) {
755 | callback = options;
756 | options = null;
757 | }
758 | options = options || {};
759 | addExtraOptions( [ 'quiet', 'depth' ], options );
760 | executeSvnXml( [ 'status', wc ], options, callback );
761 | };
762 | exports.commands.status = status;
763 | exports.commands.stat = status;
764 | exports.commands.st = status;
765 |
766 | /** Switches to a given branch / tag for a working copy
767 | * @function switch
768 | * @memberof commands
769 | * @param {string} url - Switch URL
770 | * @param {string} wc - Working copy target
771 | * @param {object} [options] - Options object
772 | * @param {function} [callback] - Complete callback
773 | */
774 | var switchf = function( url, wc, options, callback ) {
775 | if ( typeof options === 'function' ) {
776 | callback = options;
777 | options = null;
778 | }
779 | options = options || {};
780 | addExtraOptions( [ 'quiet', 'depth', 'revision', 'force' ], options );
781 | executeSvn( [ 'switch', url, wc ], options, callback );
782 | };
783 | exports.commands.switch = switchf;
784 |
785 | /** Unlocks a previously locked svn file from a working copy / repository
786 | * @function unlock
787 | * @memberof commands
788 | * @param {Array|string} targets - Working copy / URL targets
789 | * @param {object} [options] - Options object
790 | * @param {function} [callback] - Complete callback
791 | */
792 | var unlock = function( targets, options, callback ) {
793 | if ( typeof options === 'function' ) {
794 | callback = options;
795 | options = null;
796 | }
797 | if ( !Array.isArray( targets ) ) {
798 | targets = [targets];
799 | }
800 | options = options || {};
801 | addExtraOptions( [ 'force' ], options );
802 | executeSvn( [ 'unlock' ].concat( targets ), options, callback );
803 | };
804 | exports.commands.unlock = unlock;
805 |
806 | /** Updates an svn working copy
807 | * @function update
808 | * @memberof commands
809 | * @param {Array|string} wcs - Working copy targets
810 | * @param {object} [options] - Options object
811 | * @param {function} [callback] - Complete callback
812 | * @alias up
813 | */
814 | var update = function( wcs, options, callback ) {
815 | if ( typeof options === 'function' ) {
816 | callback = options;
817 | options = null;
818 | }
819 | if ( !Array.isArray( wcs ) ) {
820 | wcs = [wcs];
821 | }
822 | options = options || {};
823 | addExtraOptions( [ 'force', 'quiet', 'revision', 'depth', 'ignoreExternals' ], options );
824 | executeSvn( [ 'update' ].concat( wcs ), options, callback );
825 | };
826 | exports.commands.update = update;
827 | exports.commands.up = update;
828 |
829 | /** Upgrades a given svn working copy (requires v1.7 of svn client)
830 | * @function upgrade
831 | * @memberof commands
832 | * @param {Array|string} wcs - Working copy targets
833 | * @param {object} [options] - Options object
834 | * @param {function} [callback] - Complete callback
835 | */
836 | var upgrade = function( wcs, options, callback ) {
837 | // upgrade only works for versions of svn >= 1.7
838 | if ( typeof options === 'function' ) {
839 | callback = options;
840 | options = null;
841 | }
842 | if ( !Array.isArray( wcs ) ) {
843 | wcs = [wcs];
844 | }
845 | options = options || {};
846 | addExtraOptions( [ 'quiet' ], options );
847 |
848 | checkSvnVersion( options, ">=1.7.0", function( err, isValid ) {
849 | if ( err ) {
850 | return callback( err );
851 | }
852 | if ( isValid ) {
853 | executeSvn( [ 'upgrade' ].concat( wcs ), options, callback );
854 | } else {
855 | callback();
856 | }
857 | } );
858 | };
859 | exports.commands.upgrade = upgrade;
860 |
861 |
862 | // svnmucc
863 | /*
864 | commandArray can contain array of the following
865 | cp REV SRC-URL DST-URL : copy SRC-URL@REV to DST-URL
866 | mkdir URL : create new directory URL
867 | mv SRC-URL DST-URL : move SRC-URL to DST-URL
868 | rm URL : delete URL
869 | put SRC-FILE URL : add or modify file URL with contents copied from
870 | SRC-FILE (use "-" to read from standard input)
871 | propset NAME VALUE URL : set property NAME on URL to VALUE
872 | propsetf NAME FILE URL : set property NAME on URL to value read from FILE
873 | propdel NAME URL : delete property NAME from URL
874 | */
875 |
876 | /** Executes svnmucc command, for multiple commands
877 | * @see http://svnbook.red-bean.com/en/1.8/svn.ref.svnmucc.re.html
878 | * @function mucc
879 | * @memberof commands
880 | * @param {Array} commandArray - Array of command strings, see above link for options
881 | * @param {string} commitMessage - Commit message to use
882 | * @param {object} [options] - Options object
883 | * @param {function} [callback] - Complete callback
884 | */
885 | var mucc = function( commandArray, commitMessage, options, callback ) {
886 | if ( typeof commitMessage !== 'string' ) {
887 | throw new Error( "svnUltimate.command.mucc - commitMessage must be a string" );
888 | }
889 | if ( typeof options === 'function' ) {
890 | callback = options;
891 | options = null;
892 | }
893 | options = options || {};
894 | if ( !Array.isArray( commandArray ) ) {
895 | commandArray = [commandArray];
896 | }
897 | executeMucc( [ '-m "' + commitMessage + '"' ].concat( commandArray ), options, function( err, stdo ) {
898 | // parse the output to find the revision that has just been commited
899 | var result = null;
900 | stdo = stdo.toString().trim();
901 | try {
902 | var matches = stdo.match( /^r(\d+) committed by (.+?) at (.+)$/ );
903 | if ( matches ) { // matches should be revision, name, then iso date
904 | result = {
905 | revision: parseInt( matches[1], 10 ),
906 | user: matches[2],
907 | isodate: matches[3]
908 | };
909 | }
910 | }
911 | catch ( err2 ) {
912 | }
913 | callback( err, result );
914 | } );
915 | };
916 | exports.commands.mucc = mucc;
917 |
918 |
919 | // Utilities
920 |
921 | /** Exposes some custom utility methods
922 | * @namespace util
923 | */
924 | exports.util = {};
925 | // 'lastChangeRevision' option returns the last commit revision, instead of the working copy revision
926 |
927 | /** Gets head revision of a given URL
928 | * @function getRevision
929 | * @memberof util
930 | * @param {string} target - Target URL
931 | * @param {object} [options] - Options object
932 | * @param {function} [callback] - Complete callback
933 | */
934 | var getRevision = function( target, options, callback ) {
935 | if ( typeof options === "function" ) {
936 | callback = options;
937 | options = null;
938 | }
939 | options = options || {};
940 | info( target, options, function( err, data ) {
941 | var rev;
942 | if ( !err ) {
943 | var revString;
944 | if ( options.lastChangeRevision ) {
945 | if ( data && data.entry && data.entry.commit && data.entry.commit.$ && data.entry.commit.$.revision ) {
946 | revString = data.entry.commit.$.revision;
947 | }
948 | } else {
949 | if ( data && data.entry && data.entry.$ && data.entry.$.revision ) {
950 | revString = data.entry.$.revision;
951 | }
952 | }
953 | if ( revString !== undefined ) {
954 | try {
955 | rev = parseInt( revString, 10 );
956 | }
957 | catch ( err3 ) {
958 | err = 'Invalid revision value [' + revString + ']';
959 | }
960 | } else {
961 | err = 'Could not parse info result to get revision [' + JSON.stringify( data ) + ']';
962 | }
963 | }
964 | callback( err, rev );
965 | } );
966 | };
967 | exports.util.getRevision = getRevision;
968 |
969 |
970 | /** Gets the revision of a working copy.
971 | * @function getWorkingCopyRevision
972 | * @memberof util
973 | * @param {string} wcDir - Working copy folder
974 | * @param {object} [options] - Options object
975 | * @param {function} [callback] - Complete callback
976 | */
977 | var getWorkingCopyRevision = function( wcDir, options, callback ) {
978 | if ( typeof options === "function" ) {
979 | callback = options;
980 | options = null;
981 | }
982 | options = options || {};
983 | if ( !Array.isArray( wcDir ) ) {
984 | wcDir = [wcDir];
985 | }
986 | var args = [ '-n' ];
987 | if ( options.lastChangeRevision ) {
988 | args.push( '-c' );
989 | }
990 | execSvnVersion( wcDir.concat( args ), options, function( err, data ) {
991 | var result;
992 | if ( !err ) {
993 | var match = data.match( /(\d+):?(\d*)(\w*)/ );
994 | if ( match ) {
995 | result = {};
996 | result.low = parseInt( match[1] );
997 | if ( match[2].length > 0 ) {
998 | result.high = parseInt( match[2] );
999 | } else {
1000 | result.high = result.low;
1001 | }
1002 | result.flags = match[3];
1003 | if ( result.flags.length > 0 ) {
1004 | result.modified = result.flags.indexOf( 'M' ) >= 0;
1005 | result.partial = result.flags.indexOf( 'P' ) >= 0;
1006 | result.switched = result.flags.indexOf( 'S' ) >= 0;
1007 | }
1008 | } else {
1009 | err = data;
1010 | }
1011 | }
1012 | callback( err, result );
1013 | } );
1014 | };
1015 | exports.util.getWorkingCopyRevision = getWorkingCopyRevision;
1016 |
1017 |
1018 | /** Parse a url for an SVN project repository and breaks it apart
1019 | * @function parseUrl
1020 | * @memberof util
1021 | * @param {string} url - URL to parse
1022 | * @returns {object}
1023 | */
1024 | var parseUrl = function( url ) {
1025 | var trunkMatch = url.match( /(.*)\/(trunk|branches|tags)\/*(.*)\/*(.*)$/i );
1026 | if ( trunkMatch ) {
1027 | var rootUrl = trunkMatch[1];
1028 | var projectName = rootUrl.match( /\/([^\/]+)$/ )[1];
1029 | return {
1030 | rootUrl: rootUrl,
1031 | projectName: projectName,
1032 | type: trunkMatch[2],
1033 | typeName: trunkMatch[3],
1034 | trunkUrl: trunkMatch[1] + "/trunk",
1035 | tagsUrl: trunkMatch[1] + "/tags",
1036 | branchesUrl: trunkMatch[1] + "/branches"
1037 | };
1038 | }
1039 | throw new Error( "parseUrl: Url does not look like an SVN repository" );
1040 | };
1041 | exports.util.parseUrl = parseUrl;
1042 |
1043 | /** Gets all available tags for the given svn URL
1044 | * @function getTags
1045 | * @memberof util
1046 | * @param {string} url - Project URL to get tags for
1047 | * @param {object} [options] - Options object
1048 | * @param {function} [callback] - Complete callback
1049 | */
1050 | var getTags = function( url, options, callback ) {
1051 | if ( typeof options === "function" ) {
1052 | callback = options;
1053 | options = null;
1054 | }
1055 | options = options || {};
1056 | var tagsUrl = parseUrl( url ).tagsUrl;
1057 | list( tagsUrl, options, function( err, data ) {
1058 | var result = [];
1059 | if ( !err && data && data.list && data.list.entry ) {
1060 | if ( Array.isArray( data.list.entry ) ) {
1061 | result = data.list.entry.filter( function( entry ) {
1062 | return entry && entry.$ && entry.$.kind === "dir";
1063 | } );
1064 | } else {
1065 | if ( data.list.entry.$ && data.list.entry.$.kind === "dir" ) {
1066 | result = [ data.list.entry ];
1067 | }
1068 | }
1069 | }
1070 | callback( err, result );
1071 | } );
1072 | };
1073 | exports.util.getTags = getTags;
1074 |
1075 |
1076 | /** Uses node's semver package to work out the latest tag value
1077 | * @function getLatestTag
1078 | * @memberof util
1079 | * @param {string} url - Project URL to get latest tag for
1080 | * @param {object} options - Options object
1081 | * @param {function} [callback] - Complete callback
1082 | */
1083 | var getLatestTag = function( url, options, callback ) {
1084 | if ( typeof options === "function" ) {
1085 | callback = options;
1086 | options = null;
1087 | }
1088 | options = options || {};
1089 | getTags( url, options, function( err, tagArray ) {
1090 | var latest;
1091 | if ( !err && Array.isArray( tagArray ) && tagArray.length > 0 ) {
1092 | tagArray.sort( function( a, b ) {
1093 | try {
1094 | return semver.rcompare( a.name, b.name );
1095 | }
1096 | catch ( err2 ) {
1097 | return -1;
1098 | }
1099 | } );
1100 | latest = tagArray[0];
1101 | }
1102 | callback( err, latest );
1103 | } );
1104 | };
1105 | exports.util.getLatestTag = getLatestTag;
1106 |
1107 | /** Gets all available branches for the given svn URL
1108 | * @function getBranches
1109 | * @memberof util
1110 | * @param {string} url - Project URL to get branches for
1111 | * @param {object} [options] - Options object
1112 | * @param {function} [callback] - Complete callback
1113 | */
1114 | var getBranches = function( url, options, callback ) {
1115 | if ( typeof options === "function" ) {
1116 | callback = options;
1117 | options = null;
1118 | }
1119 | options = options || {};
1120 | var branchesUrl = parseUrl( url ).branchesUrl;
1121 | list( branchesUrl, options, function( err, data ) {
1122 | var result = [];
1123 | if ( !err && data && data.list && data.list.entry ) {
1124 | if ( Array.isArray( data.list.entry ) ) {
1125 | result = data.list.entry.filter( function( entry ) {
1126 | return entry && entry.$ && entry.$.kind === "dir";
1127 | } );
1128 | } else {
1129 | if ( data.list.entry.$ && data.list.entry.$.kind === "dir" ) {
1130 | result = [ data.list.entry ];
1131 | }
1132 | }
1133 | }
1134 | callback( err, result );
1135 | } );
1136 | };
1137 | exports.util.getBranches = getBranches;
1138 |
1139 |
1140 | /** Helper object for using SVNMUCC
1141 | */
1142 | var MuccHelper = function( options ) {
1143 | this._options = options || {};
1144 | this._commands = [];
1145 | this._options.tempFolder = this._options.tempFolder || path.join( os.tmpdir(), 'mucc_' + uuid.v4() );
1146 | };
1147 |
1148 |
1149 | MuccHelper.prototype._getTempFilename = function() {
1150 | fs.ensureDirSync( this._options.tempFolder );
1151 | for ( var count=0; true; ++count ) {
1152 | var newPath = path.join( this._options.tempFolder, uuid.v4() + ".temp" );
1153 | if ( !fs.existsSync( newPath ) ) {
1154 | return newPath;
1155 | }
1156 | }
1157 | throw new Error( "Could not find temporary filename" ); // never reached
1158 | };
1159 |
1160 |
1161 | MuccHelper.prototype.queueLength = function() {
1162 | return this._commands.length;
1163 | };
1164 |
1165 |
1166 | MuccHelper.prototype._reset = function( callback ) {
1167 | this._commands.length = 0;
1168 | if ( fs.existsSync( this._options.tempFolder ) ) {
1169 | fs.remove( this._options.tempFolder, function() { callback(); } );
1170 | } else {
1171 | callback();
1172 | }
1173 | };
1174 |
1175 |
1176 | MuccHelper.prototype.cp = function( src, dst, options ) {
1177 | options = options || {};
1178 | var str = 'cp';
1179 | if ( isFinite( options.revision ) ) {
1180 | str += '\n' + options.revision;
1181 | } else {
1182 | str += '\nHEAD';
1183 | }
1184 | str += '\n' + src;
1185 | str += '\n' + dst;
1186 | this._commands.push( str );
1187 | };
1188 |
1189 |
1190 | MuccHelper.prototype.putFile = function( filename, dst ) {
1191 | this._commands.push( 'put\n' + filename + '\n' + dst );
1192 | };
1193 |
1194 |
1195 | MuccHelper.prototype.put = function( filedata, dst ) {
1196 | var file = this._getTempFilename();
1197 | fs.writeFileSync( file, filedata );
1198 | this._commands.push( 'put\n' + file + '\n' + dst );
1199 | };
1200 |
1201 |
1202 | MuccHelper.prototype.mkdir = function( dst ) {
1203 | this._commands.push( 'mkdir\n' + dst );
1204 | };
1205 |
1206 |
1207 | MuccHelper.prototype.rm = function( dst ) {
1208 | this._commands.push( 'rm\n' + dst );
1209 | };
1210 |
1211 |
1212 | MuccHelper.prototype.commit = function( options, callback ) {
1213 | if ( typeof options === 'function' ) {
1214 | callback = options;
1215 | options = {};
1216 | }
1217 | var that = this;
1218 | options = options || {};
1219 | if ( this._commands.length > 0 ) {
1220 | // write arguments to file and pass to mucc via a temporary file to get around
1221 | // windows command line limitations
1222 | var argsFile = this._getTempFilename();
1223 | fs.writeFileSync( argsFile, this._commands.join( "\n" ) );
1224 | var params = '';
1225 | if ( options.rootUrl && options.rootUrl.length > 0 ) {
1226 | params = '--root-url "' + options.rootUrl + '"';
1227 | }
1228 | mucc(
1229 | params + ' --extra-args "' + argsFile + '"',
1230 | options.msg || 'SVNMUCC commit',
1231 | function( err, result ) {
1232 | that._reset( function( err2 ) {
1233 | callback( err || err2, result );
1234 | } );
1235 | } );
1236 | } else {
1237 | callback( null, null );
1238 | }
1239 | };
1240 |
1241 |
1242 |
1243 | exports.util.MuccHelper = MuccHelper;
1244 |
1245 |
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-svn-ultimate",
3 | "version": "1.1.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "balanced-match": {
8 | "version": "1.0.0",
9 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
10 | "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
11 | "dev": true
12 | },
13 | "brace-expansion": {
14 | "version": "1.1.11",
15 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
16 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17 | "dev": true,
18 | "requires": {
19 | "balanced-match": "^1.0.0",
20 | "concat-map": "0.0.1"
21 | }
22 | },
23 | "browser-stdout": {
24 | "version": "1.3.1",
25 | "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
26 | "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
27 | "dev": true
28 | },
29 | "commander": {
30 | "version": "2.15.1",
31 | "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz",
32 | "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==",
33 | "dev": true
34 | },
35 | "concat-map": {
36 | "version": "0.0.1",
37 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
38 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
39 | "dev": true
40 | },
41 | "debug": {
42 | "version": "3.1.0",
43 | "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
44 | "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
45 | "dev": true,
46 | "requires": {
47 | "ms": "2.0.0"
48 | }
49 | },
50 | "diff": {
51 | "version": "3.5.0",
52 | "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz",
53 | "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
54 | "dev": true
55 | },
56 | "escape-string-regexp": {
57 | "version": "1.0.5",
58 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
59 | "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
60 | "dev": true
61 | },
62 | "fs-extra": {
63 | "version": "1.0.0",
64 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz",
65 | "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=",
66 | "requires": {
67 | "graceful-fs": "^4.1.2",
68 | "jsonfile": "^2.1.0",
69 | "klaw": "^1.0.0"
70 | }
71 | },
72 | "fs.realpath": {
73 | "version": "1.0.0",
74 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
75 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
76 | "dev": true
77 | },
78 | "glob": {
79 | "version": "7.1.2",
80 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
81 | "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
82 | "dev": true,
83 | "requires": {
84 | "fs.realpath": "^1.0.0",
85 | "inflight": "^1.0.4",
86 | "inherits": "2",
87 | "minimatch": "^3.0.4",
88 | "once": "^1.3.0",
89 | "path-is-absolute": "^1.0.0"
90 | }
91 | },
92 | "graceful-fs": {
93 | "version": "4.1.15",
94 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz",
95 | "integrity": "sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA=="
96 | },
97 | "growl": {
98 | "version": "1.10.5",
99 | "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz",
100 | "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==",
101 | "dev": true
102 | },
103 | "has-flag": {
104 | "version": "3.0.0",
105 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
106 | "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
107 | "dev": true
108 | },
109 | "he": {
110 | "version": "1.1.1",
111 | "resolved": "https://registry.npmjs.org/he/-/he-1.1.1.tgz",
112 | "integrity": "sha1-k0EP0hsAlzUVH4howvJx80J+I/0=",
113 | "dev": true
114 | },
115 | "inflight": {
116 | "version": "1.0.6",
117 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
118 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
119 | "dev": true,
120 | "requires": {
121 | "once": "^1.3.0",
122 | "wrappy": "1"
123 | }
124 | },
125 | "inherits": {
126 | "version": "2.0.3",
127 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
128 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=",
129 | "dev": true
130 | },
131 | "jsonfile": {
132 | "version": "2.4.0",
133 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
134 | "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=",
135 | "requires": {
136 | "graceful-fs": "^4.1.6"
137 | }
138 | },
139 | "klaw": {
140 | "version": "1.3.1",
141 | "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
142 | "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=",
143 | "requires": {
144 | "graceful-fs": "^4.1.9"
145 | }
146 | },
147 | "minimatch": {
148 | "version": "3.0.4",
149 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
150 | "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
151 | "dev": true,
152 | "requires": {
153 | "brace-expansion": "^1.1.7"
154 | }
155 | },
156 | "minimist": {
157 | "version": "0.0.8",
158 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
159 | "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=",
160 | "dev": true
161 | },
162 | "mkdirp": {
163 | "version": "0.5.1",
164 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
165 | "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
166 | "dev": true,
167 | "requires": {
168 | "minimist": "0.0.8"
169 | }
170 | },
171 | "mocha": {
172 | "version": "5.2.0",
173 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-5.2.0.tgz",
174 | "integrity": "sha512-2IUgKDhc3J7Uug+FxMXuqIyYzH7gJjXECKe/w43IGgQHTSj3InJi+yAA7T24L9bQMRKiUEHxEX37G5JpVUGLcQ==",
175 | "dev": true,
176 | "requires": {
177 | "browser-stdout": "1.3.1",
178 | "commander": "2.15.1",
179 | "debug": "3.1.0",
180 | "diff": "3.5.0",
181 | "escape-string-regexp": "1.0.5",
182 | "glob": "7.1.2",
183 | "growl": "1.10.5",
184 | "he": "1.1.1",
185 | "minimatch": "3.0.4",
186 | "mkdirp": "0.5.1",
187 | "supports-color": "5.4.0"
188 | }
189 | },
190 | "ms": {
191 | "version": "2.0.0",
192 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
193 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
194 | "dev": true
195 | },
196 | "once": {
197 | "version": "1.4.0",
198 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
199 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
200 | "dev": true,
201 | "requires": {
202 | "wrappy": "1"
203 | }
204 | },
205 | "path-is-absolute": {
206 | "version": "1.0.1",
207 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
208 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
209 | "dev": true
210 | },
211 | "sax": {
212 | "version": "1.2.4",
213 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
214 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
215 | },
216 | "semver": {
217 | "version": "5.6.0",
218 | "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz",
219 | "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
220 | },
221 | "should": {
222 | "version": "11.2.1",
223 | "resolved": "https://registry.npmjs.org/should/-/should-11.2.1.tgz",
224 | "integrity": "sha1-kPVRRVUtAc/CAGZuToGKHJZw7aI=",
225 | "dev": true,
226 | "requires": {
227 | "should-equal": "^1.0.0",
228 | "should-format": "^3.0.2",
229 | "should-type": "^1.4.0",
230 | "should-type-adaptors": "^1.0.1",
231 | "should-util": "^1.0.0"
232 | }
233 | },
234 | "should-equal": {
235 | "version": "1.0.1",
236 | "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-1.0.1.tgz",
237 | "integrity": "sha1-C26VFvJgGp+wuy3MNpr6HH4gCvc=",
238 | "dev": true,
239 | "requires": {
240 | "should-type": "^1.0.0"
241 | }
242 | },
243 | "should-format": {
244 | "version": "3.0.3",
245 | "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz",
246 | "integrity": "sha1-m/yPdPo5IFxT04w01xcwPidxJPE=",
247 | "dev": true,
248 | "requires": {
249 | "should-type": "^1.3.0",
250 | "should-type-adaptors": "^1.0.1"
251 | }
252 | },
253 | "should-type": {
254 | "version": "1.4.0",
255 | "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz",
256 | "integrity": "sha1-B1bYzoRt/QmEOmlHcZ36DUz/XPM=",
257 | "dev": true
258 | },
259 | "should-type-adaptors": {
260 | "version": "1.1.0",
261 | "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz",
262 | "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==",
263 | "dev": true,
264 | "requires": {
265 | "should-type": "^1.3.0",
266 | "should-util": "^1.0.0"
267 | }
268 | },
269 | "should-util": {
270 | "version": "1.0.0",
271 | "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.0.tgz",
272 | "integrity": "sha1-yYzaN0qmsZDfi6h8mInCtNtiAGM=",
273 | "dev": true
274 | },
275 | "supports-color": {
276 | "version": "5.4.0",
277 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz",
278 | "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==",
279 | "dev": true,
280 | "requires": {
281 | "has-flag": "^3.0.0"
282 | }
283 | },
284 | "uuid": {
285 | "version": "3.3.2",
286 | "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz",
287 | "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA=="
288 | },
289 | "wrappy": {
290 | "version": "1.0.2",
291 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
292 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
293 | "dev": true
294 | },
295 | "xml2js": {
296 | "version": "0.4.19",
297 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
298 | "integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
299 | "requires": {
300 | "sax": ">=0.6.0",
301 | "xmlbuilder": "~9.0.1"
302 | }
303 | },
304 | "xmlbuilder": {
305 | "version": "9.0.7",
306 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
307 | "integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
308 | }
309 | }
310 | }
311 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "node-svn-ultimate",
3 | "description": "The ultimate SVN wrapper for node. Contains all the basic methods checkout, update, info, etc, and includes svnmucc support.",
4 | "version": "1.2.1",
5 | "homepage": "https://github.com/peteward44/node-svn-ultimate",
6 | "repository": {
7 | "type": "git",
8 | "url": "https://github.com/peteward44/node-svn-ultimate.git"
9 | },
10 | "author": "Pete Ward