diff --git a/CHANGELOG.md b/CHANGELOG.md index c00feb8a7..b3d69a4b9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ # Change Log -# v0.13.0 [(2016-05-04)](https://github.com/nodegit/nodegit/releases/tag/v0.13.0) +## v0.13.1 [(2016-06-03)](https://github.com/nodegit/nodegit/releases/tag/v0.13.1) + +[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.13.0...v0.13.1) + +## Added + +- `Repository#discardLines` is now a thing [PR #1021](https://github.com/nodegit/nodegit/pull/1021) + +## Modified + +- Async methods now use a custom threadpool to prevent thread-locking the event loop [PR #1019](https://github.com/nodegit/nodegit/pull/1019) + +## Bug fixes + +- Fix building NodeGit from NPM [PR #1026](https://github.com/nodegit/nodegit/pull/1026) +- Plug a memory leak in `RevWalk.fastWalk` [PR #1030](https://github.com/nodegit/nodegit/pull/1030) +- Plug a memory leak with `Oid` [PR #1033](https://github.com/nodegit/nodegit/pull/1033) +- Fixed some underlying libgit2 objects getting freed incorrectly [PR #1036](https://github.com/nodegit/nodegit/pull/1036) + +## v0.13.0 [(2016-05-04)](https://github.com/nodegit/nodegit/releases/tag/v0.13.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.12.2...v0.13.0) @@ -17,7 +36,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s ### Modified -- `Index#add`, `Index#addByPath`, `Index#clear`, `Index#conflictAdd`, `Index#conflictCleanup`, `Index#conflictGet`, `Index#conflictRemove`, `Index.open`, `Index#read`, `Index#readTree`, `Index#remove`, `Index#removeByPath`, `Index#removeDirectory`, `Index#read`, `Index#writeTree`, and `Index#writeTreeTo` are all now asynchronous functions [PR #971](https://github.com/nodegit/nodegit/pull/971) +- `Index#add`, `Index#addByPath`, `Index#clear`, `Index#conflictAdd`, `Index#conflictCleanup`, `Index#conflictGet`, `Index#conflictRemove`, `Index.open`, `Index#read`, `Index#readTree`, `Index#remove`, `Index#removeByPath`, `Index#removeDirectory`, `Index#read`, `Index#write`, `Index#writeTree`, and `Index#writeTreeTo` are all now asynchronous functions [PR #971](https://github.com/nodegit/nodegit/pull/971) - Made `ancestoryEntry`, `outEntry` and `theirEntry` optional parameters on `Index#conflictAdd` [PR #997](https://github.com/nodegit/nodegit/pull/997) - `Repository#refreshIndex` will return an Index object back that has the latest data loaded off of disk [PR #986](https://github.com/nodegit/nodegit/pull/986) - `Commit.create` is now asynchronous [PR #1022](https://github.com/nodegit/nodegit/pull/1022) @@ -102,7 +121,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s the existing callback `notify_cb` was updated to reflect that it only gets called when new deltas are added to the diff. -- `FetchOptions` and `PushOptions` have gained a `custom_headers` +- `FetchOptions` and `PushOptions` have gained a `customHeaders` field to set the extra HTTP header fields to send. - `Commit#headerField` allows you to look up a specific header @@ -150,7 +169,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s Additionally, the `TreeEntry` fields have been removed in lieu of the corresponding functions to return the data. -# v0.12.2 [(2016-04-07)](https://github.com/nodegit/nodegit/releases/tag/v0.12.2) +## v0.12.2 [(2016-04-07)](https://github.com/nodegit/nodegit/releases/tag/v0.12.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.12.1...v0.12.2) @@ -162,7 +181,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Added memory clean up for references [PR #977](https://github.com/nodegit/nodegit/pull/977) and remotes [PR #981](https://github.com/nodegit/nodegit/pull/981) -# v0.12.1 [(2016-03-30)](https://github.com/nodegit/nodegit/releases/tag/v0.12.1) +## v0.12.1 [(2016-03-30)](https://github.com/nodegit/nodegit/releases/tag/v0.12.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.12.0...v0.12.1) @@ -170,7 +189,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed post install script dying on windows [PR #978](https://github.com/nodegit/nodegit/pull/978) -# v0.12.0 [(2016-03-28)](https://github.com/nodegit/nodegit/releases/tag/v0.12.0) +## v0.12.0 [(2016-03-28)](https://github.com/nodegit/nodegit/releases/tag/v0.12.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.9...v0.12.0) @@ -187,19 +206,19 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed install when there is a space in the username on windows [PR #951](https://github.com/nodegit/nodegit/pull/951) - Bump to nan@2.2.0 [PR #952](https://github.com/nodegit/nodegit/pull/952) -# v0.11.9 [(2016-03-09)](https://github.com/nodegit/nodegit/releases/tag/v0.11.9) +## v0.11.9 [(2016-03-09)](https://github.com/nodegit/nodegit/releases/tag/v0.11.9) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.8...v0.11.9) - Fixed crash when calculating diff via `ConvenientPatch` [PR #945](https://github.com/nodegit/nodegit/pull/945) -# v0.11.8 [(2016-03-07)](https://github.com/nodegit/nodegit/releases/tag/v0.11.8) +## v0.11.8 [(2016-03-07)](https://github.com/nodegit/nodegit/releases/tag/v0.11.8) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.7...v0.11.8) - Removed callback throttling due to segmentation faults. Will be implemented later. [PR #943](https://github.com/nodegit/nodegit/pull/943) -# v0.11.7 [(2016-03-07)](https://github.com/nodegit/nodegit/releases/tag/v0.11.7) +## v0.11.7 [(2016-03-07)](https://github.com/nodegit/nodegit/releases/tag/v0.11.7) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.6...v0.11.7) @@ -209,7 +228,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed unicode in `Diff.blobToBuffer` getting corrupted [PR #935](https://github.com/nodegit/nodegit/pull/935) - Fixed fetching/pulling to bitbucket in versions > v5.6 of node [PR #942](https://github.com/nodegit/nodegit/pull/942) -# v0.11.6 [(2016-03-01)](https://github.com/nodegit/nodegit/releases/tag/v0.11.6) +## v0.11.6 [(2016-03-01)](https://github.com/nodegit/nodegit/releases/tag/v0.11.6) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.5...v0.11.6) @@ -220,27 +239,27 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed http parsing errors in Node 5.6 [PR #931](https://github.com/nodegit/nodegit/pull/931) - Fixed `Tree#walk` not returning the correct entries on `end` [PR #929](https://github.com/nodegit/nodegit/pull/929) -# v0.11.5 [(2016-02-25)](https://github.com/nodegit/nodegit/releases/tag/v0.11.5) +## v0.11.5 [(2016-02-25)](https://github.com/nodegit/nodegit/releases/tag/v0.11.5) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.4...v0.11.5) - Fixed crash when calculating a diff [PR #922](https://github.com/nodegit/nodegit/pull/922) - Fixed an issue with return values getting randomly corrupted [PR #923](https://github.com/nodegit/nodegit/pull/923)) -# v0.11.4 [(2016-02-24)](https://github.com/nodegit/nodegit/releases/tag/v0.11.4) +## v0.11.4 [(2016-02-24)](https://github.com/nodegit/nodegit/releases/tag/v0.11.4) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.3...v0.11.4) - Fixed callback out values in callbacks from C++. This affects any NodeGit call that is passed a callback as an option [PR #921](https://github.com/nodegit/nodegit/pull/921) - Fixed an issue with building the debug version of NodeGit on windows [PR #918](https://github.com/nodegit/nodegit/pull/918) -# v0.11.3 [(2016-02-22)](https://github.com/nodegit/nodegit/releases/tag/v0.11.3) +## v0.11.3 [(2016-02-22)](https://github.com/nodegit/nodegit/releases/tag/v0.11.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.2...v0.11.3) - Fixed an issue where initializing NodeGit would sometimes seg fault. Also fixed an error when fetching concurrently [PR #912](https://github.com/nodegit/nodegit/pull/912) -# v0.11.2 [(2016-02-18)](https://github.com/nodegit/nodegit/releases/tag/v0.11.2) +## v0.11.2 [(2016-02-18)](https://github.com/nodegit/nodegit/releases/tag/v0.11.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.1...v0.11.2) @@ -249,21 +268,21 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed seg-fault in linux that happens when getting the diff of very small files [PR #908](https://github.com/nodegit/nodegit/pull/908) - Fixed `RevWalk#fastWalk` dying when an error happens in libgit2 [PR #909](https://github.com/nodegit/nodegit/pull/909) -# v0.11.1 [(2016-02-09)](https://github.com/nodegit/nodegit/releases/tag/v0.11.1) +## v0.11.1 [(2016-02-09)](https://github.com/nodegit/nodegit/releases/tag/v0.11.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.11.0...v0.11.1) - Numerous fixes and perf boosts to file history [PR #900](https://github.com/nodegit/nodegit/pull/900)[PR #896](https://github.com/nodegit/nodegit/pull/896) - Several doc fixes [PR #899](https://github.com/nodegit/nodegit/pull/899)[PR #897](https://github.com/nodegit/nodegit/pull/897) -# v0.11.0 [(2016-02-04)](https://github.com/nodegit/nodegit/releases/tag/v0.11.0) +## v0.11.0 [(2016-02-04)](https://github.com/nodegit/nodegit/releases/tag/v0.11.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.10.0...v0.11.0) - Change `Revert.commit` and `Revert.revert` to by async. [PR #887](https://github.com/nodegit/nodegit/pull/887) - Added `RevWalk#fileHistoryWalk` for a faster way to retrieve history for a specific file. [PR #889](https://github.com/nodegit/nodegit/pull/889) -# v0.10.0 [(2016-02-01)](https://github.com/nodegit/nodegit/releases/tag/v0.10.0) +## v0.10.0 [(2016-02-01)](https://github.com/nodegit/nodegit/releases/tag/v0.10.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.9.0...v0.10.0) @@ -289,7 +308,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - `rawContent()` contains the unformatted content of the line. This is no longer a string from the line to the end of the file. - `content()` contains the utf8 formatted content of the line. -# v0.9.0 [(2016-01-21)](https://github.com/nodegit/nodegit/releases/tag/v0.9.0) +## v0.9.0 [(2016-01-21)](https://github.com/nodegit/nodegit/releases/tag/v0.9.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.8.0...v0.9.0) @@ -299,7 +318,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - `Repository#mergeBranches` now takes in a `MergeOptions` parameter [PR #873](https://github.com/nodegit/nodegit/pull/873) - Remove a NodeGit specific hack to make `Index#addAll` faster since that is fixed in libgit2 [PR #875](https://github.com/nodegit/nodegit/pull/875)) -# v0.8.0 [(2016-01-15)](https://github.com/nodegit/nodegit/releases/tag/v0.8.0) +## v0.8.0 [(2016-01-15)](https://github.com/nodegit/nodegit/releases/tag/v0.8.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.7.0...0.8.0) @@ -308,7 +327,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - `Repository#stageFilemode` now can accept an array of strings for files to update - `Submodule#addToIndex`, `Submodule#addFinalize`, `Submodule#init`, `Submodule#open`, `Submodule#sync`, and `Submodule#update` are now all async methodss -# v0.7.0 [(2016-01-08)](https://github.com/nodegit/nodegit/releases/tag/v0.7.0) +## v0.7.0 [(2016-01-08)](https://github.com/nodegit/nodegit/releases/tag/v0.7.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.6.3...0.7.0) @@ -317,20 +336,20 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Make GraphDescendentOf asynchronous - Fixed line length of utf8 stringss -# v0.6.3 [(2015-12-16)](https://github.com/nodegit/nodegit/releases/tag/v0.6.3) +## v0.6.3 [(2015-12-16)](https://github.com/nodegit/nodegit/releases/tag/v0.6.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.6.2...0.6.3) - Fixed a bug where manually building for vanilla node would fail without explicitly setting the target -# v0.6.2 [(2015-12-16)](https://github.com/nodegit/nodegit/releases/tag/v0.6.2) +## v0.6.2 [(2015-12-16)](https://github.com/nodegit/nodegit/releases/tag/v0.6.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.6.1...0.6.2) - Fixed a bug where manually building on windows would fail (if unable to download a prebuilt binary) -# v0.6.1 [(2015-12-14)](https://github.com/nodegit/nodegit/releases/tag/v0.6.1) +## v0.6.1 [(2015-12-14)](https://github.com/nodegit/nodegit/releases/tag/v0.6.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.6.0...0.6.1) @@ -338,7 +357,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Added Repository.getSubmoduleNames - Added Submodule.Foreach -# v0.6.0 [(2015-12-08)](https://github.com/nodegit/nodegit/releases/tag/v0.6.0) +## v0.6.0 [(2015-12-08)](https://github.com/nodegit/nodegit/releases/tag/v0.6.0) - Added file mode staging - Added a fast rev walk to do the rev walk in C++ and bubble the result up to JS @@ -349,7 +368,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed weirdness in lifecycle scripts - Added downloading prebuilt binaries for electron -# v0.4.1 [(2015-06-02)](https://github.com/nodegit/nodegit/tree/0.4.1) +## v0.4.1 [(2015-06-02)](https://github.com/nodegit/nodegit/tree/0.4.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.4.0...0.4.1) @@ -413,7 +432,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - stop cleaning on post-install [\#562](https://github.com/nodegit/nodegit/pull/562) ([maxkorp](https://github.com/maxkorp)) -# v0.4.0 [(2015-05-07)](https://github.com/nodegit/nodegit/tree/v0.4.0) +## v0.4.0 [(2015-05-07)](https://github.com/nodegit/nodegit/tree/v0.4.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.3.3...v0.4.0) @@ -541,7 +560,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Add automatically generated change log file. [\#465](https://github.com/nodegit/nodegit/pull/465) ([skywinder](https://github.com/skywinder)) -# v0.3.3 [(2015-03-16)](https://github.com/nodegit/nodegit/tree/v0.3.3) +## v0.3.3 [(2015-03-16)](https://github.com/nodegit/nodegit/tree/v0.3.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.3.2...v0.3.3) @@ -549,7 +568,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Download all dev dependencies before build [\#491](https://github.com/nodegit/nodegit/pull/491) ([johnhaley81](https://github.com/johnhaley81)) -# v0.3.2 [(2015-03-16)](https://github.com/nodegit/nodegit/tree/v0.3.2) +## v0.3.2 [(2015-03-16)](https://github.com/nodegit/nodegit/tree/v0.3.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.3.1...v0.3.2) @@ -561,7 +580,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Confirm builder exists before building [\#490](https://github.com/nodegit/nodegit/pull/490) ([johnhaley81](https://github.com/johnhaley81)) -# v0.3.1 [(2015-03-14)](https://github.com/nodegit/nodegit/tree/v0.3.1) +## v0.3.1 [(2015-03-14)](https://github.com/nodegit/nodegit/tree/v0.3.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.3.0...v0.3.1) @@ -569,7 +588,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Revert node-pre-gyp to install not build [\#486](https://github.com/nodegit/nodegit/pull/486) ([tbranyen](https://github.com/tbranyen)) -# v0.3.0 [(2015-03-13)](https://github.com/nodegit/nodegit/tree/v0.3.0) +## v0.3.0 [(2015-03-13)](https://github.com/nodegit/nodegit/tree/v0.3.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.7...v0.3.0) @@ -779,11 +798,11 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Enable transfer progress [\#325](https://github.com/nodegit/nodegit/pull/325) ([tbranyen](https://github.com/tbranyen)) -# v0.2.7 [(2015-01-21)](https://github.com/nodegit/nodegit/tree/v0.2.7) +## v0.2.7 [(2015-01-21)](https://github.com/nodegit/nodegit/tree/v0.2.7) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.6...v0.2.7) -# v0.2.6 [(2015-01-20)](https://github.com/nodegit/nodegit/tree/v0.2.6) +## v0.2.6 [(2015-01-20)](https://github.com/nodegit/nodegit/tree/v0.2.6) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.5...v0.2.6) @@ -791,7 +810,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - \[WIP\] Added in some diff functions from libgit2 [\#348](https://github.com/nodegit/nodegit/pull/348) ([johnhaley81](https://github.com/johnhaley81)) -# v0.2.5 [(2015-01-20)](https://github.com/nodegit/nodegit/tree/v0.2.5) +## v0.2.5 [(2015-01-20)](https://github.com/nodegit/nodegit/tree/v0.2.5) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.4...v0.2.5) @@ -857,7 +876,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - moving some deps to devdeps [\#320](https://github.com/nodegit/nodegit/pull/320) ([maxkorp](https://github.com/maxkorp)) -# v0.2.4 [(2014-12-05)](https://github.com/nodegit/nodegit/tree/v0.2.4) +## v0.2.4 [(2014-12-05)](https://github.com/nodegit/nodegit/tree/v0.2.4) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.3...v0.2.4) @@ -909,11 +928,11 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Styling [\#295](https://github.com/nodegit/nodegit/pull/295) ([maxkorp](https://github.com/maxkorp)) -# v0.2.3 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.3) +## v0.2.3 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.2...v0.2.3) -# v0.2.2 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.2) +## v0.2.2 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.1...v0.2.2) @@ -921,7 +940,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Moved some dependencies around to help the generate not fail [\#294](https://github.com/nodegit/nodegit/pull/294) ([johnhaley81](https://github.com/johnhaley81)) -# v0.2.1 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.1) +## v0.2.1 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.2.0...v0.2.1) @@ -929,7 +948,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Rewrite installer [\#293](https://github.com/nodegit/nodegit/pull/293) ([johnhaley81](https://github.com/johnhaley81)) -# v0.2.0 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.0) +## v0.2.0 [(2014-11-25)](https://github.com/nodegit/nodegit/tree/v0.2.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.1.4...v0.2.0) @@ -1121,7 +1140,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Better installation flow for developing. [\#180](https://github.com/nodegit/nodegit/pull/180) ([tbranyen](https://github.com/tbranyen)) -# v0.1.4 [(2014-06-13)](https://github.com/nodegit/nodegit/tree/v0.1.4) +## v0.1.4 [(2014-06-13)](https://github.com/nodegit/nodegit/tree/v0.1.4) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.1.3...v0.1.4) @@ -1143,7 +1162,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fixed: "ReferenceError: error is not defined" [\#169](https://github.com/nodegit/nodegit/pull/169) ([danyshaanan](https://github.com/danyshaanan)) -# v0.1.3 [(2014-05-02)](https://github.com/nodegit/nodegit/tree/v0.1.3) +## v0.1.3 [(2014-05-02)](https://github.com/nodegit/nodegit/tree/v0.1.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.1.2...v0.1.3) @@ -1151,7 +1170,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Fix erroneous OS detection for installation in OS X. [\#156](https://github.com/nodegit/nodegit/pull/156) ([tbranyen](https://github.com/tbranyen)) -# v0.1.2 [(2014-05-02)](https://github.com/nodegit/nodegit/tree/v0.1.2) +## v0.1.2 [(2014-05-02)](https://github.com/nodegit/nodegit/tree/v0.1.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.1.1...v0.1.2) @@ -1189,7 +1208,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - WIP New installer. [\#140](https://github.com/nodegit/nodegit/pull/140) ([tbranyen](https://github.com/tbranyen)) -# v0.1.1 [(2014-03-23)](https://github.com/nodegit/nodegit/tree/v0.1.1) +## v0.1.1 [(2014-03-23)](https://github.com/nodegit/nodegit/tree/v0.1.1) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.1.0...v0.1.1) @@ -1267,7 +1286,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Add system dependencies for OSX install [\#82](https://github.com/nodegit/nodegit/pull/82) ([philschatz](https://github.com/philschatz)) -# v0.1.0 [(2013-09-07)](https://github.com/nodegit/nodegit/tree/v0.1.0) +## v0.1.0 [(2013-09-07)](https://github.com/nodegit/nodegit/tree/v0.1.0) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.79...v0.1.0) @@ -1301,7 +1320,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Updated LICENSE to MIT [\#75](https://github.com/nodegit/nodegit/pull/75) ([tbranyen](https://github.com/tbranyen)) -# v0.0.79 [(2013-04-05)](https://github.com/nodegit/nodegit/tree/v0.0.79) +## v0.0.79 [(2013-04-05)](https://github.com/nodegit/nodegit/tree/v0.0.79) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.778...v0.0.79) @@ -1311,7 +1330,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Python error on installing nodegit 0.0.77 [\#59](https://github.com/nodegit/nodegit/issues/59) -# v0.0.778 [(2013-03-26)](https://github.com/nodegit/nodegit/tree/v0.0.778) +## v0.0.778 [(2013-03-26)](https://github.com/nodegit/nodegit/tree/v0.0.778) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.77...v0.0.778) @@ -1319,15 +1338,15 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - See issue \#59 [\#60](https://github.com/nodegit/nodegit/pull/60) ([dctr](https://github.com/dctr)) -# v0.0.77 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.77) +## v0.0.77 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.77) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.76...v0.0.77) -# v0.0.76 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.76) +## v0.0.76 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.76) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.75...v0.0.76) -# v0.0.75 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.75) +## v0.0.75 [(2013-03-24)](https://github.com/nodegit/nodegit/tree/v0.0.75) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.74...v0.0.75) @@ -1357,11 +1376,11 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Comment all code methods [\#1](https://github.com/nodegit/nodegit/issues/1) -# v0.0.74 [(2013-03-21)](https://github.com/nodegit/nodegit/tree/v0.0.74) +## v0.0.74 [(2013-03-21)](https://github.com/nodegit/nodegit/tree/v0.0.74) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.73...v0.0.74) -# v0.0.73 [(2013-03-21)](https://github.com/nodegit/nodegit/tree/v0.0.73) +## v0.0.73 [(2013-03-21)](https://github.com/nodegit/nodegit/tree/v0.0.73) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.72...v0.0.73) @@ -1375,11 +1394,11 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Tree each method is synchronous [\#15](https://github.com/nodegit/nodegit/issues/15) -# v0.0.72 [(2013-03-06)](https://github.com/nodegit/nodegit/tree/v0.0.72) +## v0.0.72 [(2013-03-06)](https://github.com/nodegit/nodegit/tree/v0.0.72) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.71...v0.0.72) -# v0.0.71 [(2013-03-06)](https://github.com/nodegit/nodegit/tree/v0.0.71) +## v0.0.71 [(2013-03-06)](https://github.com/nodegit/nodegit/tree/v0.0.71) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.6...v0.0.71) @@ -1407,7 +1426,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Refactor [\#37](https://github.com/nodegit/nodegit/pull/37) ([mmalecki](https://github.com/mmalecki)) -# v0.0.6 [(2011-12-19)](https://github.com/nodegit/nodegit/tree/v0.0.6) +## v0.0.6 [(2011-12-19)](https://github.com/nodegit/nodegit/tree/v0.0.6) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.4...v0.0.6) @@ -1421,7 +1440,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Node 0.6x fixes [\#34](https://github.com/nodegit/nodegit/pull/34) ([moneal](https://github.com/moneal)) -# v0.0.4 [(2011-05-14)](https://github.com/nodegit/nodegit/tree/v0.0.4) +## v0.0.4 [(2011-05-14)](https://github.com/nodegit/nodegit/tree/v0.0.4) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.3...v0.0.4) @@ -1433,7 +1452,7 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Branch history each method is asynchronous [\#11](https://github.com/nodegit/nodegit/issues/11) -# v0.0.3 [(2011-04-13)](https://github.com/nodegit/nodegit/tree/v0.0.3) +## v0.0.3 [(2011-04-13)](https://github.com/nodegit/nodegit/tree/v0.0.3) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.2...v0.0.3) @@ -1443,11 +1462,11 @@ We have added Node 6 as a supported platform! Going forward we aim to have 1:1 s - Windows link issue [\#12](https://github.com/nodegit/nodegit/issues/12) -# v0.0.2 [(2011-03-14)](https://github.com/nodegit/nodegit/tree/v0.0.2) +## v0.0.2 [(2011-03-14)](https://github.com/nodegit/nodegit/tree/v0.0.2) [Full Changelog](https://github.com/nodegit/nodegit/compare/v0.0.1...v0.0.2) -# v0.0.1 [(2011-03-10)](https://github.com/nodegit/nodegit/tree/v0.0.1) +## v0.0.1 [(2011-03-10)](https://github.com/nodegit/nodegit/tree/v0.0.1) diff --git a/README.md b/README.md index 6e8c09e2c..d7047dac6 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ NodeGit -**Stable: 0.12.2** +**Stable: 0.13.1** ## Have a problem? Come chat with us! ## diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json index fbe9fd4fc..650fc9faa 100644 --- a/generate/input/descriptor.json +++ b/generate/input/descriptor.json @@ -1452,7 +1452,7 @@ "ignore": true }, "oid": { - "selfFreeing": "true", + "selfFreeing": true, "cpyFunction": "git_oid_cpy", "freeFunctionName": "free", "shouldAlloc": true, diff --git a/generate/templates/manual/include/async_libgit2_queue_worker.h b/generate/templates/manual/include/async_libgit2_queue_worker.h new file mode 100644 index 000000000..f3ddf2fb3 --- /dev/null +++ b/generate/templates/manual/include/async_libgit2_queue_worker.h @@ -0,0 +1,33 @@ +#ifndef ASYNC_LIBGIT2_QUEUE_WORKER_H +#define ASYNC_LIBGIT2_QUEUE_WORKER_H + +#include +#include +#include "../include/thread_pool.h" +#include "../include/nodegit.h" + + +// Runs WorkComplete of the scheduled AsyncWorker, +// and destroys it. This is run in the uv_default_loop event loop. +NAN_INLINE void AsyncLibgit2Complete (void* data) { + Nan::AsyncWorker *worker = static_cast(data); + worker->WorkComplete(); + worker->Destroy(); +} + +// Runs Execute of the scheduled AyncWorker on the dedicated libgit2 thread / +// event loop, and schedules the WorkComplete callback to run on the +// uv_default_loop event loop +NAN_INLINE void AsyncLibgit2Execute (void *vworker) { + // execute the worker + Nan::AsyncWorker *worker = static_cast(vworker); + worker->Execute(); +} + +// Schedules the AsyncWorker to run on the dedicated libgit2 thread / event loop, +// and on completion AsyncLibgit2Complete on the default loop +NAN_INLINE void AsyncLibgit2QueueWorker (Nan::AsyncWorker* worker) { + libgit2ThreadPool.QueueWork(AsyncLibgit2Execute, AsyncLibgit2Complete, worker); +} + +#endif diff --git a/generate/templates/manual/include/nodegit.h b/generate/templates/manual/include/nodegit.h new file mode 100644 index 000000000..4408b8ea7 --- /dev/null +++ b/generate/templates/manual/include/nodegit.h @@ -0,0 +1,8 @@ +#ifndef NODEGIT_H +#define NODEGIT_H + +#include "thread_pool.h" + +extern ThreadPool libgit2ThreadPool; + +#endif diff --git a/generate/templates/manual/include/thread_pool.h b/generate/templates/manual/include/thread_pool.h new file mode 100644 index 000000000..6d29b3ddf --- /dev/null +++ b/generate/templates/manual/include/thread_pool.h @@ -0,0 +1,45 @@ +#ifndef THREAD_POOL_H +#define THREAD_POOL_H + +#include +#include + +class ThreadPool { + typedef void (*Callback) (void *); + struct Work { + Callback workCallback; + Callback loopCallback; + void *data; + + Work(Callback workCallback, Callback loopCallback, void *data) + : workCallback(workCallback), loopCallback(loopCallback), data(data) { + } + }; + + // work to be performed on the threadpool + std::queue workQueue; + uv_mutex_t workMutex; + uv_sem_t workSemaphore; + int workInProgressCount; + + // completion callbacks to be performed on the loop + std::queue loopQueue; + uv_mutex_t loopMutex; + uv_async_t loopAsync; + + static void RunEventQueue(void *threadPool); + void RunEventQueue(); + static void RunLoopCallbacks(uv_async_t* handle); + void RunLoopCallbacks(); +public: + // Initializes thread pool and spins up the requested number of threads + // The provided loop will be used for completion callbacks, whenever + // queued work is completed + ThreadPool(int numberOfThreads, uv_loop_t *loop); + // Queues work on the thread pool, followed by completion call scheduled + // on the loop provided in the constructor. + // QueueWork should be called on the loop provided in the constructor. + void QueueWork(Callback workCallback, Callback loopCallback, void *data); +}; + +#endif diff --git a/generate/templates/manual/revwalk/fast_walk.cc b/generate/templates/manual/revwalk/fast_walk.cc index 4a2ad7ea5..a7e3c54f3 100644 --- a/generate/templates/manual/revwalk/fast_walk.cc +++ b/generate/templates/manual/revwalk/fast_walk.cc @@ -73,9 +73,11 @@ void GitRevwalk::FastWalkWorker::HandleOKCallback() unsigned int size = baton->out->size(); Local result = Nan::New(size); for (unsigned int i = 0; i < size; i++) { - Nan::Set(result, Nan::New(i), GitOid::New(baton->out->at(i), false)); + Nan::Set(result, Nan::New(i), GitOid::New(baton->out->at(i), true)); } + delete baton->out; + Local argv[2] = { Nan::Null(), result diff --git a/generate/templates/manual/src/nodegit_wrapper.cc b/generate/templates/manual/src/nodegit_wrapper.cc index e22468a99..ea6694425 100644 --- a/generate/templates/manual/src/nodegit_wrapper.cc +++ b/generate/templates/manual/src/nodegit_wrapper.cc @@ -11,6 +11,7 @@ NodeGitWrapper::NodeGitWrapper(typename Traits::cType *raw, bool selfFre } else { this->owner.Reset(owner); this->raw = raw; + selfFreeing = false; } } else { this->raw = raw; diff --git a/generate/templates/manual/src/thread_pool.cc b/generate/templates/manual/src/thread_pool.cc new file mode 100644 index 000000000..abf7a29a8 --- /dev/null +++ b/generate/templates/manual/src/thread_pool.cc @@ -0,0 +1,85 @@ +#include "../include/thread_pool.h" + +ThreadPool::ThreadPool(int numberOfThreads, uv_loop_t *loop) { + uv_mutex_init(&workMutex); + uv_sem_init(&workSemaphore, 0); + + uv_async_init(loop, &loopAsync, RunLoopCallbacks); + loopAsync.data = this; + uv_unref((uv_handle_t *)&loopAsync); + uv_mutex_init(&loopMutex); + + workInProgressCount = 0; + + for(int i=0; i(threadPool)->RunEventQueue(); +} + +void ThreadPool::RunEventQueue() { + for ( ; ; ) { + // wait until there is work to do + uv_sem_wait(&workSemaphore); + uv_mutex_lock(&workMutex); + // the semaphore should guarantee that queue is not empty + Work work = workQueue.front(); + workQueue.pop(); + uv_mutex_unlock(&workMutex); + + // perform the queued work + (*work.workCallback)(work.data); + + // schedule the callback on the loop + uv_mutex_lock(&loopMutex); + loopQueue.push(work); + uv_mutex_unlock(&loopMutex); + uv_async_send(&loopAsync); + } +} + +void ThreadPool::RunLoopCallbacks(uv_async_t* handle) { + static_cast(handle->data)->RunLoopCallbacks(); +} + +void ThreadPool::RunLoopCallbacks() { + // uv_async_send can coalesce calls, so we are not guaranteed one + // RunLoopCallbacks per uv_async_send call + // so we always process the entire loopQueue + int callbacksCompleted = 0; + uv_mutex_lock(&loopMutex); + while(!loopQueue.empty()) { + Work work = loopQueue.front(); + loopQueue.pop(); + uv_mutex_unlock(&loopMutex); + // perform the queued loop callback + (*work.loopCallback)(work.data); + callbacksCompleted++; + uv_mutex_lock(&loopMutex); + } + uv_mutex_unlock(&loopMutex); + + uv_mutex_lock(&workMutex); + // if there is no ongoing work / completion processing, node doesn't need + // to be prevented from terminating + workInProgressCount -= callbacksCompleted; + if(!workInProgressCount) { + uv_unref((uv_handle_t *)&loopAsync); + } + uv_mutex_unlock(&workMutex); +} diff --git a/generate/templates/partials/async_function.cc b/generate/templates/partials/async_function.cc index 7b564adb2..edfae89df 100644 --- a/generate/templates/partials/async_function.cc +++ b/generate/templates/partials/async_function.cc @@ -74,7 +74,7 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) { {%endif%} {%endeach%} - Nan::AsyncQueueWorker(worker); + AsyncLibgit2QueueWorker(worker); return; } diff --git a/generate/templates/templates/binding.gyp b/generate/templates/templates/binding.gyp index 9a2813579..dbc60874a 100644 --- a/generate/templates/templates/binding.gyp +++ b/generate/templates/templates/binding.gyp @@ -22,6 +22,7 @@ "src/convenient_patch.cc", "src/convenient_hunk.cc", "src/str_array_converter.cc", + "src/thread_pool.cc", {% each %} {% if type != "enum" %} "src/{{ name }}.cc", diff --git a/generate/templates/templates/class_content.cc b/generate/templates/templates/class_content.cc index b8084baa6..834361884 100644 --- a/generate/templates/templates/class_content.cc +++ b/generate/templates/templates/class_content.cc @@ -12,6 +12,7 @@ extern "C" { #include "../include/functions/copy.h" #include "../include/{{ filename }}.h" #include "nodegit_wrapper.cc" +#include "../include/async_libgit2_queue_worker.h" {% each dependencies as dependency %} #include "{{ dependency }}" diff --git a/generate/templates/templates/nodegit.cc b/generate/templates/templates/nodegit.cc index 189a4d622..2cde41c12 100644 --- a/generate/templates/templates/nodegit.cc +++ b/generate/templates/templates/nodegit.cc @@ -10,6 +10,7 @@ #include "../include/init_ssh2.h" #include "../include/lock_master.h" +#include "../include/nodegit.h" #include "../include/wrapper.h" #include "../include/promise_completion.h" #include "../include/functions/copy.h" @@ -80,6 +81,8 @@ void OpenSSL_ThreadSetup() { CRYPTO_set_id_callback(OpenSSL_IDCallback); } +ThreadPool libgit2ThreadPool(10, uv_default_loop()); + extern "C" void init(Local target) { // Initialize thread safety in openssl and libssh2 OpenSSL_ThreadSetup(); diff --git a/lib/remote.js b/lib/remote.js index 29b157c1a..93a8461c1 100644 --- a/lib/remote.js +++ b/lib/remote.js @@ -26,7 +26,7 @@ Remote.lookup = lookupWrapper(Remote); * @param {Enums.DIRECTION} direction The direction for the connection * @param {RemoteCallbacks} callbacks The callback functions for the connection * @param {ProxyOptions} proxyOpts Proxy settings - * @param {Array[String]} customHeaders extra HTTP headers to use + * @param {Array} customHeaders extra HTTP headers to use * @param {Function} callback * @return {Number} error code */ diff --git a/lib/repository.js b/lib/repository.js index 371f4d0b2..e3d66a94e 100644 --- a/lib/repository.js +++ b/lib/repository.js @@ -1311,204 +1311,217 @@ Repository.prototype.stageFilemode = function(filePath, stageNew) { }); }; -/** - * Stages or unstages line selection of a specified file - * - * @async - * @param {String} filePath The relative path of this file in the repo - * @param {Array} newLines The array of DiffLine objects - * selected for staging or unstaging - * @param {Boolean} isStaged Are the selected lines currently staged - * @return {Number} 0 or an error code - */ -Repository.prototype.stageLines = - function(filePath, selectedLines, isSelectionStaged) { +function getPathHunks(repo, index, filePath, isStaged) { + return Promise.resolve() + .then(function() { + if (isStaged) { + return repo.getHeadCommit() + .then(function getTreeFromCommit(commit) { + return commit.getTree(); + }) + .then(function getDiffFromTree(tree) { + return NodeGit.Diff.treeToIndex(repo, tree, index); + }); + } - function applySelectedLinesToBlob - (pathHunks, isStaged, newLines, originalBlob) { - var lineTypes = { - ADDED: 43, // ascii code for '+' - DELETED: 45 // ascii code for '-' - }; - var newContent = ""; - var oldIndex = 0; - var linesPromises = []; + return NodeGit.Diff.indexToWorkdir(repo, index, { + flags: + NodeGit.Diff.OPTION.SHOW_UNTRACKED_CONTENT | + NodeGit.Diff.OPTION.RECURSE_UNTRACKED_DIRS + }); + }) + .then(function(diff) { + if (!(NodeGit.Status.file(repo, filePath) & + NodeGit.Status.STATUS.WT_MODIFIED) && + !(NodeGit.Status.file(repo, filePath) & + NodeGit.Status.STATUS.INDEX_MODIFIED)) { + return Promise.reject + ("Selected staging is only available on modified files."); + } - //split the original file into lines - var oldLines = originalBlob.toString().split("\n"); + return diff.patches(); + }) + .then(function(patches) { + var pathPatch = patches.filter(function(patch) { + return patch.newFile().path() === filePath; + }); - //if no selected lines were sent, return the original content - if (!newLines || newLines.length === 0) { - return originalBlob; - } + if (pathPatch.length !== 1) { + return Promise.reject("No differences found for this file."); + } - function lineEqualsFirstNewLine(hunkLine) { - return ((hunkLine.oldLineno() === newLines[0].oldLineno()) && - (hunkLine.newLineno() === newLines[0].newLineno())); - } + return pathPatch[0].hunks(); + }); +} - function processSelectedLine(hunkLine) { - //if this hunk line is a selected line find the selected line - var newLine = newLines.filter(function(nLine) { - return ((hunkLine.oldLineno() === nLine.oldLineno()) && - (hunkLine.newLineno() === nLine.newLineno())); - }); +function applySelectedLinesToTarget + (originalContent, newLines, pathHunks, isStaged, reverse) { + // 43: ascii code for '+' + // 45: ascii code for '-' + var lineTypes = { + ADDED: !reverse ? 43 : 45, + DELETED: !reverse ? 45 : 43 + }; + var newContent = ""; + var oldIndex = 0; + var linesPromises = []; - if (hunkLine.content() - .indexOf("\\ No newline at end of file") != -1) { - return false; - } + // split the original file into lines + var oldLines = originalContent.toString().split("\n"); - //determine what to add to the new content - if ((isStaged && newLine && newLine.length > 0) || - (!isStaged && (!newLine || newLine.length === 0))) { - if (hunkLine.origin() !== lineTypes.ADDED) { - newContent += hunkLine.content(); - } - if ((isStaged && hunkLine.origin() !== lineTypes.DELETED) || - (!isStaged && hunkLine.origin() !== lineTypes.ADDED)) { - oldIndex++; - } - } - else { - switch (hunkLine.origin()) { - case lineTypes.ADDED: - newContent += hunkLine.content(); - if (isStaged) { - oldIndex++; - } - break; - case lineTypes.DELETED: - if (!isStaged) { - oldIndex++; - } - break; - default: - newContent += oldLines[oldIndex++]; - if (oldIndex < oldLines.length) { - newContent += "\n"; - } - break; - } - } - } + // if no selected lines were sent, return the original content + if (!newLines || newLines.length === 0) { + return originalContent; + } - //find the affected hunk - pathHunks.forEach(function(pathHunk) { - linesPromises.push(pathHunk.lines()); + function lineEqualsFirstNewLine(hunkLine) { + return ((hunkLine.oldLineno() === newLines[0].oldLineno()) && + (hunkLine.newLineno() === newLines[0].newLineno())); + } + + function processSelectedLine(hunkLine) { + // if this hunk line is a selected line find the selected line + var newLine = newLines.filter(function(nLine) { + return ((hunkLine.oldLineno() === nLine.oldLineno()) && + (hunkLine.newLineno() === nLine.newLineno())); }); - return Promise.all(linesPromises).then(function(results) { - for (var index = 0; index < results.length && - newContent.length < 1; index++) { - var hunkStart = isStaged ? pathHunks[index].newStart() - : pathHunks[index].oldStart(); - var lines = results[index]; - if (lines.filter(lineEqualsFirstNewLine).length > 0) { - //add content that is before the hunk - while (hunkStart > (oldIndex + 1)) { - newContent += oldLines[oldIndex++] + "\n"; - } - //modify the lines of the hunk according to the selection - lines.forEach(processSelectedLine); + if (hunkLine.content().indexOf("\\ No newline at end of file") !== -1) { + return false; + } - //add the rest of the file - while (oldLines.length > oldIndex) { - newContent += oldLines[oldIndex++] + - (oldLines.length > oldIndex ? "\n" : ""); + // determine what to add to the new content + if ((isStaged && newLine && newLine.length > 0) || + (!isStaged && (!newLine || newLine.length === 0))) { + if (hunkLine.origin() !== lineTypes.ADDED) { + newContent += hunkLine.content(); + } + if ((isStaged && hunkLine.origin() !== lineTypes.DELETED) || + (!isStaged && hunkLine.origin() !== lineTypes.ADDED)) { + oldIndex++; + } + } + else { + switch (hunkLine.origin()) { + case lineTypes.ADDED: + newContent += hunkLine.content(); + if (isStaged) { + oldIndex++; } - } + break; + case lineTypes.DELETED: + if (!isStaged) { + oldIndex++; + } + break; + default: + newContent += oldLines[oldIndex++]; + if (oldIndex < oldLines.length) { + newContent += "\n"; + } + break; } - return newContent; - }); + } } - var repo = this; - var index; - var diffPromise = function diffPromise() { - return isSelectionStaged ? - repo.getHeadCommit() - .then(function getTreeFromCommit(commit) { - return commit.getTree(); - }) - .then(function getDiffFromTree(tree) { - return NodeGit.Diff.treeToIndex(repo, tree, index); - }) - : - NodeGit.Diff.indexToWorkdir(repo, index, { - flags: - NodeGit.Diff.OPTION.SHOW_UNTRACKED_CONTENT | - NodeGit.Diff.OPTION.RECURSE_UNTRACKED_DIRS - }); - }; + // find the affected hunk + pathHunks.forEach(function(pathHunk) { + linesPromises.push(pathHunk.lines()); + }); - //The following chain checks if there is a patch with no hunks left for the - //file, and no filemode changes were done on the file. It is then safe to - //stage the entire file so the file doesn't show as having unstaged changes - //in `git status`. Also, check if there are no type changes. - var lastHunkStagedPromise = function lastHunkStagedPromise(result) { - return NodeGit.Diff.indexToWorkdir(repo, index, { - flags: - NodeGit.Diff.OPTION.SHOW_UNTRACKED_CONTENT | - NodeGit.Diff.OPTION.RECURSE_UNTRACKED_DIRS - }) - .then(function (diff) { - return diff.patches(); - }) - .then(function(patches) { - var pathPatch = patches.filter(function(patch) { - return patch.newFile().path() === filePath; - }); - var emptyPatch = false; - if (pathPatch.length > 0) { - //No hunks, unchanged file mode, and no type changes. - emptyPatch = pathPatch[0].size() === 0 && - pathPatch[0].oldFile().mode() == pathPatch[0].newFile().mode() && - !pathPatch[0].isTypeChange(); + return Promise.all(linesPromises).then(function(results) { + for (var i = 0; i < results.length && newContent.length < 1; i++) { + var hunkStart = isStaged || reverse ? pathHunks[i].newStart() + : pathHunks[i].oldStart(); + var lines = results[i]; + if (lines.filter(lineEqualsFirstNewLine).length > 0) { + // add content that is before the hunk + while (hunkStart > (oldIndex + 1)) { + newContent += oldLines[oldIndex++] + "\n"; } - if (emptyPatch) { - return index.addByPath(filePath) - .then(function() { - return index.write(); - }); - } else { - return result; + + // modify the lines of the hunk according to the selection + lines.forEach(processSelectedLine); + + // add the rest of the file + while (oldLines.length > oldIndex) { + newContent += oldLines[oldIndex++] + + (oldLines.length > oldIndex ? "\n" : ""); } - }); - }; + } + } + return newContent; + }); +} - return repo.refreshIndex() - .then(function(indexResult) { - index = indexResult; - }) - .then(function() { - return diffPromise(); +/** + * Stages or unstages line selection of a specified file + * + * @async + * @param {String} filePath The relative path of this file in the repo + * @param {Array} selectedLines The array of DiffLine objects + * selected for staging or unstaging + * @param {Boolean} isStaged Are the selected lines currently staged + * @return {Number} 0 or an error code + */ +Repository.prototype.stageLines = + function(filePath, selectedLines, isSelectionStaged) { + + var repo = this; + var index; + var originalBlob; + + // The following chain checks if there is a patch with no hunks left for the + // file, and no filemode changes were done on the file. It is then safe to + // stage the entire file so the file doesn't show as having unstaged changes + // in `git status`. Also, check if there are no type changes. + var lastHunkStagedPromise = function lastHunkStagedPromise(result) { + return NodeGit.Diff.indexToWorkdir(repo, index, { + flags: + NodeGit.Diff.OPTION.SHOW_UNTRACKED_CONTENT | + NodeGit.Diff.OPTION.RECURSE_UNTRACKED_DIRS }) .then(function(diff) { - if (!(NodeGit.Status.file(repo, filePath) & - NodeGit.Status.STATUS.WT_MODIFIED) && - !(NodeGit.Status.file(repo, filePath) & - NodeGit.Status.STATUS.INDEX_MODIFIED)) { - return Promise.reject - ("Selected staging is only available on modified files."); - } return diff.patches(); }) .then(function(patches) { - var pathOid = index.getByPath(filePath).id; var pathPatch = patches.filter(function(patch) { return patch.newFile().path() === filePath; }); - if (pathPatch.length !== 1) { - return Promise.reject("No differences found for this file."); + var emptyPatch = false; + if (pathPatch.length > 0) { + // No hunks, unchanged file mode, and no type changes. + emptyPatch = pathPatch[0].size() === 0 && + pathPatch[0].oldFile().mode() === pathPatch[0].newFile().mode() && + !pathPatch[0].isTypeChange(); } - return Promise.all([repo.getBlob(pathOid), pathPatch[0].hunks()]); + if (emptyPatch) { + return index.addByPath(filePath) + .then(function() { + return index.write(); + }); + } + + return result; + }); + }; + + return repo.refreshIndex() + .then(function(indexResult) { + index = indexResult; + var pathOid = index.getByPath(filePath).id; + + return repo.getBlob(pathOid); + }) + .then(function(blob) { + originalBlob = blob; + + return getPathHunks(repo, index, filePath, isSelectionStaged); }) - .then(function(results) { - var originalBlob = results[0]; - var pathHunks = results[1]; - return applySelectedLinesToBlob( - pathHunks, isSelectionStaged, selectedLines, originalBlob); + .then(function(hunks) { + return applySelectedLinesToTarget( + originalBlob, selectedLines, hunks, isSelectionStaged + ); }) .then(function(newContent) { var newContentBuffer = new Buffer(newContent); @@ -1530,9 +1543,46 @@ Repository.prototype.stageLines = .then(function(result) { if (isSelectionStaged) { return result; - } else { - return lastHunkStagedPromise(result); } + + return lastHunkStagedPromise(result); + }); +}; + +/** + * Discard line selection of a specified file. + * Assumes selected lines are unstaged. + * + * @async + * @param {String} filePath The relative path of this file in the repo + * @param {Array} selectedLines The array of DiffLine objects + * selected for discarding + * @return {Number} 0 or an error code + */ +Repository.prototype.discardLines = function(filePath, selectedLines) { + var repo = this; + var fullFilePath = path.join(repo.workdir(), filePath); + var index; + var originalContent; + + return repo.refreshIndex() + .then(function(indexResult) { + index = indexResult; + + return fse.readFile(fullFilePath, "utf8"); + }) + .then(function(content) { + originalContent = content; + + return getPathHunks(repo, index, filePath, false); + }) + .then(function(hunks) { + return applySelectedLinesToTarget( + originalContent, selectedLines, hunks, false, true + ); + }) + .then(function(newContent) { + return fse.writeFile(fullFilePath, newContent); }); }; diff --git a/lifecycleScripts/submodules/getStatus.js b/lifecycleScripts/submodules/getStatus.js index a6b3f801c..53c85c1f3 100644 --- a/lifecycleScripts/submodules/getStatus.js +++ b/lifecycleScripts/submodules/getStatus.js @@ -5,6 +5,13 @@ var exec = require(path.join(rootDir, "./utils/execPromise")); module.exports = function getStatus() { return exec("git submodule status", { cwd: rootDir}) .then(function(stdout) { + if (!stdout) { + // In the case where we pull from npm they pre-init the submodules for + // us and `git submodule status` returns empty-string. In that case + // we'll just assume that we're good. + return Promise.resolve([]); + } + function getStatusPromiseFromLine(line) { var lineSections = line.trim().split(" "); var onNewCommit = !!~lineSections[0].indexOf("+"); diff --git a/package.json b/package.json index 60ad78d7f..1dc406e66 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "nodegit", "description": "Node.js libgit2 asynchronous native bindings", - "version": "0.13.0", + "version": "0.13.1", "homepage": "http://nodegit.org", "keywords": [ "libgit2", diff --git a/test/tests/stage.js b/test/tests/stage.js index ac0675492..248c3e0f1 100644 --- a/test/tests/stage.js +++ b/test/tests/stage.js @@ -25,7 +25,7 @@ describe("Stage", function() { return fse.remove(test.repository.workdir()); }); - function stagingTest(staging, newFileContent) { + function stagingTest(isUnstaged, newFileContent, discarding) { var fileContent = newFileContent || "One line of text\n" + "Two lines of text\n"+ @@ -48,13 +48,22 @@ describe("Stage", function() { "Nineteen lines of text\n"+ "Twenty lines of text\n"; var fileName = "stagedLinesTest.txt"; - var stagedFile; + var expectedContent; var workingDirFile; var getDiffFunction; - if (staging) { - stagedFile = fileContent.replace("Fifteen", "Changed fifteen"); - workingDirFile = stagedFile.replace("Three", "Changed three") + + if (!isUnstaged || discarding) { + expectedContent = fileContent.replace("Three", "Changed three") .replace("Seventeen", "Changed seventeen"); + workingDirFile = expectedContent.replace("Fifteen", "Changed fifteen"); + } + else { + expectedContent = fileContent.replace("Fifteen", "Changed fifteen"); + workingDirFile = expectedContent.replace("Three", "Changed three") + .replace("Seventeen", "Changed seventeen"); + } + + if (isUnstaged) { getDiffFunction = function() { return test.repository.refreshIndex() .then(function(index) { @@ -71,10 +80,6 @@ describe("Stage", function() { }; } else { - stagedFile = fileContent.replace("Three", "Changed three") - .replace("Seventeen", "Changed seventeen"); - workingDirFile = stagedFile.replace("Fifteen", "Changed fifteen"); - getDiffFunction = function() { return RepoUtils.addFileToIndex(test.repository, fileName) .then(function() { @@ -138,17 +143,28 @@ describe("Stage", function() { } }); }); - return test.repository.stageLines(fileName, linesToStage, !staging); + + if (discarding) { + return test.repository.discardLines(fileName, linesToStage); + } + + return test.repository.stageLines(fileName, linesToStage, !isUnstaged); }) .then(function() { - return test.repository.refreshIndex(); - }) - .then(function(reloadedIndex) { - var pathOid = reloadedIndex.getByPath(fileName).id; - return test.repository.getBlob(pathOid); + if (discarding) { + return fse.readFile( + path.join(test.repository.workdir(), fileName), "utf8" + ); + } + + return test.repository.refreshIndex() + .then(function(reloadedIndex) { + var pathOid = reloadedIndex.getByPath(fileName).id; + return test.repository.getBlob(pathOid); + }); }) .then(function(resultFileContents) { - assert.equal(resultFileContents.toString(), stagedFile); + assert.equal(resultFileContents.toString(), expectedContent); }); } @@ -501,4 +517,8 @@ describe("Stage", function() { return compareFilemodes(false, freshIndex, 0 /* expect nochange */); }); }); + + it("can discard selected lines", function() { + return stagingTest(true, null, true); + }); });