diff --git a/CHANGELOG.md b/CHANGELOG.md
index 19b54cd1a..24a325fce 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,66 @@
# Change Log
+## v0.24.0-alpha.1 [(2018-10-25)](https://github.com/nodegit/nodegit/releases/tag/v0.24.0-alpha.1)
+
+[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.23.0...v0.24.0-alpha.1)
+
+#### Summary of changes
+- Garbage collect most of the library.
+- All free functions have been removed. The expectation is that they will be collected by the GC.
+- All init options methods have been removed. They were never supposed to be exposed in the first place.
+
+##### Removed methods
+Mostly due to missing support anyway, please report anything you were using as an issue.
+ - NodeGit.Blob.createFromStreamCommit
+ - NodeGit.Branch.Iterator.prototype.new
+ - NodeGit.Config.initBackend
+ - NodeGit.Config.prototype.snapshot
+ - NodeGit.Config.prototype.setBool
+ - NodeGit.Config.prototype.setInt32
+ - NodeGit.Config.prototype.setInt64
+ - NodeGit.Index.prototype.owner
+ - NodeGit.Note.iteratorNew
+ - NodeGit.Note.next
+ - NodeGit.Odb.prototype.addDiskAlternate
+ - NodeGit.Repository.prototype.configSnapshot
+ - NodeGit.Signature.prototype.dup
+ - NodeGit.Tag.foreach
+ - NodeGit.Transport.init
+ - NodeGit.Transport.sshWithPaths
+ - NodeGit.Transport.unregister
+
+##### Newly exposed methods:
+ - NodeGit.Config.prototype.getEntry
+ - NodeGit.Config.prototype.snapshot
+ - NodeGit.Config.prototype.refresh
+ - NodeGit.Config.prototype.setBool
+ - NodeGit.Config.prototype.setInt32
+ - NodeGit.Config.prototype.setInt64
+ - NodeGit.Diff.prototype.isSortedIcase
+ - NodeGit.DiffStats.prototype.deletions
+ - NodeGit.DiffStats.prototype.filesChanged
+ - NodeGit.DiffStats.prototype.insertions
+ - NodeGit.DiffStats.prototype.toBuf
+ - NodeGit.Odb.hashfile
+ - NodeGit.Odb.prototype.readPrefix
+ - NodeGit.OidShorten.prototype.add
+ - NodeGit.OidShorten.create
+ - NodeGit.PathspecMatchList.prototype.diffEntry
+ - NodeGit.PathspecMatchList.prototype.entry
+ - NodeGit.PathspecMatchList.prototype.entrycount
+ - NodeGit.PathspecMatchList.prototype.failedEntry
+ - NodeGit.PathspecMatchList.prototype.failedEntryCount
+
+##### Newly exposed types
+ - NodeGit.DescribeFormatOptions
+ - NodeGit.DiffStats
+ - NodeGit.OidShorten
+ - NodeGit.PathspecMatchList
+
+#### Merged PRs into NodeGit
+- [Garbage collection: Free mostly everything automatically #1570](https://github.com/nodegit/nodegit/pull/1570)
+
+
## v0.23.0 [(2018-10-22)](https://github.com/nodegit/nodegit/releases/tag/v0.23.0)
[Full Changelog](https://github.com/nodegit/nodegit/compare/v0.22.2...v0.23.0)
diff --git a/generate/input/descriptor.json b/generate/input/descriptor.json
index 35e6ee2b9..096d4df9b 100644
--- a/generate/input/descriptor.json
+++ b/generate/input/descriptor.json
@@ -76,11 +76,35 @@
"types":
{
"annotated_commit": {
+ "selfFreeing": true,
"functions": {
+ "git_annotated_commit_free": {
+ "ignore": true
+ },
"git_annotated_commit_id": {
"return": {
"ownedByThis": true
}
+ },
+ "git_annotated_commit_from_ref": {
+ "return": {
+ "ownedBy": ["repo"]
+ }
+ },
+ "git_annotated_commit_from_fetchhead": {
+ "return": {
+ "ownedBy": ["repo"]
+ }
+ },
+ "git_annotated_commit_lookup": {
+ "return": {
+ "ownedBy": ["repo"]
+ }
+ },
+ "git_annotated_commit_from_revspec": {
+ "return": {
+ "ownedBy": ["repo"]
+ }
}
}
},
@@ -115,14 +139,41 @@
}
},
"blame": {
+ "selfFreeing": true,
"cType": "git_blame",
"functions": {
+ "git_blame_buffer": {
+ "args": {
+ "out": {
+ "ownedBy": ["reference"]
+ }
+ }
+ },
"git_blame_file": {
"args": {
+ "out": {
+ "ownedBy": ["repo"]
+ },
"options": {
"isOptional": true
}
}
+ },
+ "git_blame_free": {
+ "ignore": true
+ },
+ "git_blame_get_hunk_byindex": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
+ "git_blame_get_hunk_byline": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
+ "git_blame_init_options": {
+ "ignore": true
}
}
},
@@ -135,6 +186,10 @@
},
"blob": {
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_blob_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_blob_create_frombuffer": {
"isAsync": true,
@@ -173,7 +228,10 @@
"isErrorCode": true
}
},
- "git_blob_create_fromchunks": {
+ "git_blob_create_fromstream": {
+ "ignore": true
+ },
+ "git_blob_create_fromstream_commit": {
"ignore": true
},
"git_blob_filtered_content": {
@@ -206,6 +264,9 @@
"isErrorCode": true
}
},
+ "git_blob_free": {
+ "ignore": true
+ },
"git_blob_id": {
"return": {
"ownedByThis": true
@@ -213,6 +274,7 @@
},
"git_blob_rawcontent": {
"return": {
+ "ownedByThis": true,
"cppClassName": "Wrapper",
"jsClassName": "Buffer"
}
@@ -225,9 +287,6 @@
},
"branch": {
"functions": {
- "git_branch_iterator_free": {
- "ignore": true
- },
"git_branch_create": {
"args": {
"force": {
@@ -258,6 +317,12 @@
"isErrorCode": true
}
},
+ "git_branch_iterator_free": {
+ "ignore": true
+ },
+ "git_branch_iterator_new": {
+ "ignore": true
+ },
"git_branch_next": {
"ignore": true
},
@@ -314,6 +379,9 @@
},
"buf": {
"functions": {
+ "git_buf_free": {
+ "ignore": true
+ },
"git_buf_grow": {
"cppFunctionName": "Grow",
"jsFunctionName": "grow",
@@ -405,6 +473,9 @@
"isErrorCode": true
}
},
+ "git_checkout_init_options": {
+ "ignore": true
+ },
"git_checkout_tree": {
"args": {
"treeish": {
@@ -428,6 +499,9 @@
"return": {
"isErrorCode": true
}
+ },
+ "git_cherrypick_init_options": {
+ "ignore": true
}
}
},
@@ -439,6 +513,9 @@
"isOptional": true
}
}
+ },
+ "git_clone_init_options": {
+ "ignore": true
}
}
},
@@ -460,6 +537,10 @@
},
"commit": {
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_commit_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_commit_amend": {
"isAsync": true,
@@ -558,6 +639,9 @@
"git_commit_extract_signature": {
"isAsync": true
},
+ "git_commit_free": {
+ "ignore": true
+ },
"git_commit_id": {
"return": {
"ownedByThis": true
@@ -589,6 +673,7 @@
}
},
"config": {
+ "selfFreeing": true,
"functions": {
"git_config_add_backend": {
"ignore": true
@@ -620,6 +705,19 @@
"isErrorCode": true
}
},
+ "git_config_find_programdata": {
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ },
+ "args": {
+ "out": {
+ "isReturn": true,
+ "isSelf": false,
+ "shouldAlloc": true
+ }
+ }
+ },
"git_config_find_system": {
"isAsync": true,
"args": {
@@ -657,7 +755,12 @@
"ignore": true
},
"git_config_get_entry": {
- "ignore": true
+ "args": {
+ "out": {
+ "isReturn": true,
+ "ownedByThis": true
+ }
+ }
},
"git_config_get_int32": {
"ignore": true
@@ -698,6 +801,9 @@
"isErrorCode": true
}
},
+ "git_config_init_backend": {
+ "ignore": true
+ },
"git_config_iterator_free": {
"ignore": true
},
@@ -707,8 +813,14 @@
"git_config_iterator_new": {
"ignore": true
},
- "git_config_init_backend": {
- "ignore": true
+ "git_config_lock": {
+ "isAsync": true,
+ "args": {
+ "tx": {
+ "isReturn": true,
+ "ownedByThis": true
+ }
+ }
},
"git_config_lookup_map_value": {
"ignore": true
@@ -757,33 +869,32 @@
"git_config_parse_path": {
"ignore": true
},
- "git_config_refresh": {
- "ignore": true
- },
"git_config_set_bool": {
- "ignore": true
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
},
"git_config_set_int32": {
- "ignore": true
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
},
- "git_config_set_string": {
+ "git_config_set_int64": {
"isAsync": true,
"return": {
"isErrorCode": true
}
},
- "git_config_find_programdata": {
+ "git_config_set_string": {
"isAsync": true,
"return": {
"isErrorCode": true
- },
- "args": {
- "out": {
- "isReturn": true,
- "isSelf": false,
- "shouldAlloc": true
- }
}
+ },
+ "git_config_snapshot": {
+ "ignore": true
}
},
"dependencies": [
@@ -793,15 +904,22 @@
"config_backend": {
"ignore": true
},
+ "config_entry": {
+ "selfFreeing": true
+ },
"config_iterator": {
"ignore": true
},
"cred": {
+ "selfFreeing": true,
"cType": "git_cred",
"functions": {
"git_cred_default_new": {
"isAsync": false
},
+ "git_cred_free": {
+ "ignore": true
+ },
"git_cred_ssh_custom_new": {
"ignore": true
},
@@ -822,6 +940,9 @@
}
}
},
+ "cred_default": {
+ "ignore": true
+ },
"cred_ssh_custom": {
"ignore": true
},
@@ -832,17 +953,10 @@
"ignore": true
},
"cred_username": {
- "fields": {
- "username": {
- "cppClassName": "String",
- "cType": "char *"
- }
- }
+ "ignore": true
},
"cred_userpass_payload": {
- "cDependencies": [
- "git2/cred_helpers.h"
- ]
+ "ignore": true
},
"cred_userpass_plaintext": {
"ignore": true
@@ -850,7 +964,11 @@
"describe": {
"ignore": true
},
+ "describe_format_options": {
+ "hasConstructor": true
+ },
"diff": {
+ "selfFreeing": true,
"cDependencies": [
"git2/sys/diff.h"
],
@@ -933,11 +1051,48 @@
"git_diff_free": {
"ignore": true
},
+ "git_diff_get_perfdata": {
+ "isAsync": false,
+ "args": {
+ "out": {
+ "isReturn": true,
+ "shouldAlloc": true
+ },
+ "diff": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
"git_diff_get_stats": {
- "ignore": true
+ "isAsync": true,
+ "args": {
+ "out": {
+ "isReturn": true,
+ "ownedByThis": true
+ },
+ "diff": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_diff_index_to_index": {
+ "args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ }
+ }
},
"git_diff_index_to_workdir": {
"args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ },
"index": {
"isOptional": true
},
@@ -949,12 +1104,12 @@
"git_diff_init_options": {
"ignore": true
},
- "git_diff_is_sorted_icase": {
- "ignore": true
- },
"git_diff_merge": {
"isAsync": true,
"args": {
+ "from": {
+ "ownedByThis": true
+ },
"onto": {
"isSelf": true
}
@@ -966,6 +1121,9 @@
"git_diff_num_deltas_of_type": {
"ignore": true
},
+ "git_diff_patchid_init_options": {
+ "ignore": true
+ },
"git_diff_print": {
"ignore": true
},
@@ -975,21 +1133,6 @@
"git_diff_print_callback__to_file_handle": {
"ignore": true
},
- "git_diff_stats_deletions": {
- "ignore": true
- },
- "git_diff_stats_files_changed": {
- "ignore": true
- },
- "git_diff_stats_free": {
- "ignore": true
- },
- "git_diff_stats_insertions": {
- "ignore": true
- },
- "git_diff_stats_to_buf": {
- "ignore": true
- },
"git_diff_status_char": {
"ignore": true
},
@@ -1008,6 +1151,9 @@
},
"git_diff_tree_to_index": {
"args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ },
"old_tree": {
"isOptional": true
},
@@ -1021,6 +1167,9 @@
},
"git_diff_tree_to_tree": {
"args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ },
"old_tree": {
"isOptional": true
},
@@ -1034,6 +1183,9 @@
},
"git_diff_tree_to_workdir": {
"args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ },
"old_tree": {
"isOptional": true
},
@@ -1044,6 +1196,9 @@
},
"git_diff_tree_to_workdir_with_index": {
"args": {
+ "diff": {
+ "ownedBy": ["repo"]
+ },
"old_tree": {
"isOptional": true
},
@@ -1066,6 +1221,7 @@
"ignore": true
},
"diff_perfdata": {
+ "selfFreeing": true,
"cDependencies": [
"git2/sys/diff.h"
]
@@ -1073,127 +1229,176 @@
"diff_similarity_metric": {
"ignore": true
},
- "error_code": {
- "values": {
- "GIT_ERROR": {
- "JsName": "ERROR"
- }
- }
- },
- "filter": {
- "selfFreeing": false,
- "hasConstructor": true,
+ "diff_stats": {
+ "selfFreeing": true,
"functions": {
- "git_filter_list_apply_to_blob": {
- "async": true,
- "return": {
- "isErrorCode": true
- },
+ "git_diff_stats_deletions": {
"args": {
- "out": {
- "isReturn": true,
- "shouldAlloc": true
- },
- "filters": {
+ "stats": {
"isSelf": true
}
}
},
- "git_filter_list_apply_to_data": {
- "async": true,
- "return": {
- "isErrorCode": true
- },
+ "git_diff_stats_files_changed": {
"args": {
- "out": {
- "isReturn": true,
- "shouldAlloc": true
- },
- "filters": {
+ "stats": {
"isSelf": true
}
}
},
- "git_filter_list_apply_to_file": {
- "async": true,
- "return": {
- "isErrorCode": true
- },
+ "git_diff_stats_free": {
+ "ignore": true
+ },
+ "git_diff_stats_insertions": {
"args": {
- "out": {
- "isReturn": true,
- "shouldAlloc": true
- },
- "filters": {
+ "stats": {
"isSelf": true
}
}
},
- "git_filter_list_free": {
- "async": true,
+ "git_diff_stats_to_buf": {
+ "cppFunctionName": "DiffStatsToBuf",
+ "isAsync": true,
"args": {
- "filters": {
+ "stats": {
"isSelf": true
}
}
- },
- "git_filter_list_load": {
- "async": true,
- "return": {
- "isErrorCode": true
- },
- "args": {
- "filters": {
- "isReturn": true,
- "cType": "git_filter_list **"
- },
- "repo": {
- "cType": "git_repository *"
- },
- "blob": {
- "isOptional": true,
- "cType": "git_blob *"
- }
- }
- },
- "git_filter_list_push": {
+ }
+ }
+ },
+ "error_code": {
+ "values": {
+ "GIT_ERROR": {
+ "JsName": "ERROR"
+ }
+ }
+ },
+ "fetch": {
+ "functions": {
+ "git_fetch_init_options": {
"ignore": true
- },
- "git_filter_source_filemode": {
+ }
+ }
+ },
+ "filter": {
+ "selfFreeing": false,
+ "hasConstructor": true,
+ "cDependencies": [
+ "git2/sys/filter.h"
+ ],
+ "fields": {
+ "stream": {
"ignore": true
+ }
+ }
+ },
+ "filter_source": {
+ "functions": {
+ "git_filter_source_filemode": {
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ }
},
"git_filter_source_flags": {
- "ignore": true
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ }
},
"git_filter_source_id": {
- "ignore": true
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "ownedByThis": true
+ }
},
"git_filter_source_mode": {
- "ignore": true
- },
- "git_filter_source_options": {
- "ignore": true
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ }
},
"git_filter_source_path": {
- "ignore": true
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ }
},
"git_filter_source_repo": {
- "ignore": true
+ "isPrototypeMethod": true,
+ "args": {
+ "src": {
+ "isSelf": true
+ }
+ }
}
},
"cDependencies": [
"git2/sys/filter.h"
- ],
- "fields": {
- "stream": {
+ ]
+ },
+ "filter_list": {
+ "selfFreeing": true,
+ "functions": {
+ "git_filter_list_apply_to_blob": {
+ "isPrototypeMethod": true,
+ "args": {
+ "filters": {
+ "isSelf": true
+ },
+ "out": {
+ "shouldAlloc": true
+ }
+ }
+ },
+ "git_filter_list_apply_to_data": {
+ "isPrototypeMethod": true,
+ "args": {
+ "filters": {
+ "isSelf": true
+ },
+ "out": {
+ "shouldAlloc": true
+ }
+ }
+ },
+ "git_filter_list_apply_to_file": {
+ "isPrototypeMethod": true,
+ "args": {
+ "filters": {
+ "isSelf": true
+ },
+ "out": {
+ "shouldAlloc": true
+ }
+ }
+ },
+ "git_filter_list_free": {
+ "ignore": true
+ },
+ "git_filter_list_new": {
+ "ignore": true
+ },
+ "git_filter_list_push": {
"ignore": true
}
- }
- },
- "filter_source": {
- "ignore": false,
- "cDependencies": [
- "git2/sys/filter.h"
+ },
+ "dependencies": [
+ "../include/filter_registry.h"
]
},
"graph": {
@@ -1223,6 +1428,12 @@
}
},
"hashsig": {
+ "selfFreeing": true,
+ "functions": {
+ "git_hashsig_free": {
+ "ignore": true
+ }
+ },
"cDependencies": [
"git2/sys/hashsig.h"
]
@@ -1244,6 +1455,11 @@
}
},
"index": {
+ "selfFreeing": true,
+ "ownerFn": {
+ "name": "git_index_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_index_add": {
"isAsync": true,
@@ -1317,13 +1533,16 @@
"git_index_conflict_get": {
"args": {
"ancestor_out": {
- "isReturn": true
+ "isReturn": true,
+ "ownedBy": ["index"]
},
"our_out": {
- "isReturn": true
+ "isReturn": true,
+ "ownedBy": ["index"]
},
"their_out": {
- "isReturn": true
+ "isReturn": true,
+ "ownedBy": ["index"]
}
},
"isAsync": true,
@@ -1389,9 +1608,13 @@
"git_index_open": {
"isAsync": true,
"return": {
+ "selfOwned": true,
"isErrorCode": true
}
},
+ "git_index_owner": {
+ "ignore": true
+ },
"git_index_read": {
"args": {
"force": {
@@ -1444,6 +1667,12 @@
"isErrorCode": true
}
},
+ "git_index_reuc_get_byindex": {
+ "ignore": true
+ },
+ "git_index_reuc_get_bypath": {
+ "ignore": true
+ },
"git_index_update_all": {
"args": {
"pathspec": {
@@ -1494,33 +1723,10 @@
"ignoreInit": true
},
"indexer": {
- "cType": "git_indexer",
- "functions": {
- "git_indexer_append": {
- "ignore": true
- },
- "git_indexer_hash": {
- "return": {
- "ownedByThis": true
- }
- },
- "git_indexer_new": {
- "ignore": true
- }
- }
+ "ignore": true
},
"mempack": {
- "functions": {
- "git_mempack_dump": {
- "ignore": true
- },
- "git_mempack_new": {
- "ignore": true
- },
- "git_mempack_reset": {
- "ignore": true
- }
- }
+ "ignore": true
},
"merge": {
"functions": {
@@ -1575,16 +1781,6 @@
}
}
},
- "git_merge_trees": {
- "args": {
- "ancestor_tree": {
- "isOptional": true
- },
- "opts": {
- "isOptional": true
- }
- }
- },
"git_merge_file": {
"ignore": true
},
@@ -1594,48 +1790,106 @@
"git_merge_file_init_options": {
"ignore": true
},
- "git_merge_file_result_free": {
+ "git_merge_init_options": {
"ignore": true
+ },
+ "git_merge_trees": {
+ "args": {
+ "ancestor_tree": {
+ "isOptional": true
+ },
+ "opts": {
+ "isOptional": true
+ }
+ }
}
}
},
"merge_driver": {
"ignore": true
},
+ "merge_driver_source": {
+ "ignore": true
+ },
+ "merge_file_result": {
+ "ignore": true
+ },
+ "merge_result": {
+ "ignore": true
+ },
"message": {
- "functions": {
- "git_message_prettify": {
- "ignore": true
- },
- "git_message_trailers": {
- "ignore": true
- }
- }
+ "ignore": true
+ },
+ "message_trailer": {
+ "ignore": true
+ },
+ "message_trailer_array": {
+ "ignore": true
},
"note": {
+ "selfFreeing": true,
"functions": {
- "git_note_iterator_free": {
- "ignore": true
+ "git_note_author": {
+ "return": {
+ "ownedByThis": true
+ }
},
- "git_note_create": {
+ "git_note_commit_create": {
"args": {
- "out": {
+ "notes_commit_out": {
+ "isReturn": true,
+ "shouldAlloc": true
+ },
+ "notes_blob_out": {
+ "isReturn": true,
"shouldAlloc": true
}
}
},
- "git_note_id": {
+ "git_note_commit_remove": {
+ "isAsync": true,
+ "args": {
+ "notes_commit_out": {
+ "isReturn": true
+ }
+ }
+ },
+ "git_note_comitter": {
"return": {
"ownedByThis": true
}
},
- "git_note_remove": {
+ "git_note_create": {
+ "args": {
+ "out": {
+ "shouldAlloc": true
+ }
+ }
+ },
+ "git_note_foreach": {
"isAsync": true,
"return": {
"isErrorCode": true
}
},
- "git_note_foreach": {
+ "git_note_free": {
+ "ignore": true
+ },
+ "git_note_id": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
+ "git_note_iterator_free": {
+ "ignore": true
+ },
+ "git_note_iterator_new": {
+ "ignore": true
+ },
+ "git_note_next": {
+ "ignore": true
+ },
+ "git_note_remove": {
"isAsync": true,
"return": {
"isErrorCode": true
@@ -1644,7 +1898,15 @@
}
},
"object": {
+ "selfFreeing": true,
+ "ownerFn": {
+ "name": "git_object_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
+ "git_object_free": {
+ "ignore": true
+ },
"git_object_id": {
"return": {
"ownedByThis": true
@@ -1660,6 +1922,7 @@
}
},
"odb": {
+ "selfFreeing": true,
"functions": {
"git_odb_add_alternate": {
"ignore": true
@@ -1667,6 +1930,9 @@
"git_odb_add_backend": {
"ignore": true
},
+ "git_odb_add_disk_alternate": {
+ "ignore": true
+ },
"git_odb_backend_loose": {
"ignore": true
},
@@ -1677,14 +1943,37 @@
"ignore": true
},
"git_odb_exists": {
- "ignore": true
+ "ignore": true,
+ "isAsync": true,
+ "args": {
+ "db": {
+ "isSelf": true
+ }
+ }
},
"git_odb_exists_prefix": {
+ "isAsync": true,
+ "args": {
+ "db": {
+ "isSelf": true
+ },
+ "out": {
+ "isReturn": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_odb_expand_ids": {
"ignore": true
},
"git_odb_foreach": {
"ignore": true
},
+ "git_odb_free": {
+ "ignore": true
+ },
"git_odb_get_backend": {
"ignore": true
},
@@ -1692,7 +1981,15 @@
"ignore": true
},
"git_odb_hashfile": {
- "ignore": true
+ "isAsync": true,
+ "args": {
+ "out": {
+ "isReturn": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
},
"git_odb_init_backend": {
"ignore": true
@@ -1709,27 +2006,27 @@
"git_odb_open_wstream": {
"ignore": true
},
+ "git_odb_read": {
+ "cppFunctionName": "OdbRead",
+ "args": {
+ "out": {
+ "ownedByThis": true
+ }
+ }
+ },
"git_odb_read_header": {
"ignore": true
},
"git_odb_read_prefix": {
- "ignore": true
+ "args": {
+ "out": {
+ "ownedByThis": true
+ }
+ }
},
"git_odb_refresh": {
"ignore": true
},
- "git_odb_stream_finalize_write": {
- "ignore": true
- },
- "git_odb_stream_free": {
- "ignore": true
- },
- "git_odb_stream_read": {
- "ignore": true
- },
- "git_odb_stream_write": {
- "ignore": true
- },
"git_odb_write": {
"args": {
"data": {
@@ -1754,14 +2051,25 @@
},
"ignore": true
},
+ "odb_expand_id": {
+ "ignore": true
+ },
"odb_object": {
+ "selfFreeing": true,
"functions": {
"git_odb_object_data": {
"return": {
+ "ownedByThis": true,
"cppClassName": "Wrapper",
"jsClassName": "Buffer"
}
},
+ "git_odb_object_dup": {
+ "ignore": true
+ },
+ "git_odb_object_free": {
+ "ignore": true
+ },
"git_odb_object_id": {
"return": {
"ownedByThis": true
@@ -1813,15 +2121,6 @@
"git_oid_pathfmt": {
"ignore": true
},
- "git_oid_shorten_add": {
- "ignore": true
- },
- "git_oid_shorten_free": {
- "ignore": true
- },
- "git_oid_shorten_new": {
- "ignore": true
- },
"git_oid_tostr": {
"ignore": true
}
@@ -1832,21 +2131,75 @@
}
}
},
+ "oid_shorten": {
+ "selfFreeing": true,
+ "functions": {
+ "git_oid_shorten_new": {
+ "isPrototypeMethod": false
+ },
+ "git_oid_shorten_add": {
+ "args": {
+ "os": {
+ "isSelf": true
+ }
+ }
+ },
+ "git_oid_shorten_free": {
+ "ignore": true
+ }
+ }
+ },
+ "oidarray": {
+ "selfFreeing": true,
+ "functions": {
+ "git_oidarray_free": {
+ "ignore": true
+ }
+ }
+ },
"openssl": {
"cDependencies": [
"git2/sys/openssl.h"
]
},
"packbuilder": {
+ "selfFreeing": true,
"functions": {
"git_packbuilder_foreach": {
"ignore": true
},
+ "git_packbuilder_free": {
+ "ignore": true
+ },
"git_packbuilder_hash": {
"return": {
"ownedByThis": true
}
},
+ "git_packbuilder_insert": {
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_packbuilder_insert_commit": {
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_packbuilder_insert_recur": {
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_packbuilder_insert_walk": {
+ "isAsync": true,
+ "return": {
+ "isErrorCode": true
+ }
+ },
"git_packbuilder_new": {
"isAsync": false
},
@@ -1855,10 +2208,14 @@
},
"git_packbuilder_write": {
"ignore": true
+ },
+ "git_packbuilder_write_buf": {
+ "ignore": true
}
}
},
"patch": {
+ "selfFreeing": true,
"dependencies": [
"../include/convenient_patch.h"
],
@@ -1875,13 +2232,19 @@
"git_patch_from_diff": {
"isAsync": true,
"return": {
- "isErrorCode": true
+ "ownedBy": ["diff"]
+ }
+ },
+ "git_patch_get_delta": {
+ "return": {
+ "ownedByThis": true
}
},
"git_patch_get_hunk": {
"args": {
"out": {
- "returnName": "hunk"
+ "returnName": "hunk",
+ "ownedByThis": true
},
"lines_in_hunk": {
"shouldAlloc": true,
@@ -1896,6 +2259,11 @@
},
"git_patch_get_line_in_hunk": {
"isAsync": true,
+ "args": {
+ "out": {
+ "ownedByThis": true
+ }
+ },
"return": {
"isErrorCode": true
}
@@ -1925,37 +2293,97 @@
}
},
"pathspec": {
+ "selfFreeing": true,
"dependencies": [
"../include/str_array_converter.h"
],
"functions": {
- "git_pathspec_match_list_free": {
+ "git_pathspec_free": {
"ignore": true
},
+ "git_pathspec_match_diff": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedBy": ["diff"],
+ "ownedByThis": true
+ }
+ }
+ },
+ "git_pathspec_match_index": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedBy": ["index"],
+ "ownedByThis": true
+ }
+ }
+ },
"git_pathspec_new": {
"isAsync": false
+ },
+ "git_pathspec_match_tree": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedBy": ["tree"],
+ "ownedByThis": true
+ }
+ }
+ },
+ "git_pathspec_match_workdir": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedBy": ["repo"],
+ "ownedByThis": true
+ }
+ }
}
}
},
- "push": {
- "cType": "git_push",
+ "pathspec_match_list": {
+ "selfFreeing": true,
"functions": {
- "git_push_finish": {
- "isAsync": true,
+ "git_pathspec_match_list_diff_entry": {
"return": {
- "isErrorCode": true
+ "ownedByThis": true
}
},
- "git_push_set_callbacks": {
+ "git_pathspec_match_list_free": {
"ignore": true
- },
- "git_push_status_foreach": {
+ }
+ }
+ },
+ "proxy": {
+ "functions": {
+ "git_proxy_init_options": {
"ignore": true
}
}
},
+ "push": {
+ "ignore": true
+ },
"rebase": {
+ "selfFreeing": true,
"functions": {
+ "git_rebase_abort": {
+ "isAsync": true,
+ "args": {
+ "rebase": {
+ "cType": "git_rebase *",
+ "cppClassName": "GitRebase",
+ "jsClassName": "Rebase",
+ "isOptional": false,
+ "isSelf": true,
+ "isReturn": false
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
"git_rebase_commit": {
"isAsync": true,
"args": {
@@ -1992,6 +2420,9 @@
},
"git_rebase_init": {
"args": {
+ "out": {
+ "ownedBy": ["repo"]
+ },
"upstream": {
"isOptional": true
},
@@ -2006,29 +2437,53 @@
}
}
},
- "git_rebase_abort": {
- "isAsync": true,
+ "git_rebase_init_options": {
+ "ignore": true
+ },
+ "git_rebase_inmemory_index": {
"args": {
- "rebase": {
- "cType": "git_rebase *",
- "cppClassName": "GitRebase",
- "jsClassName": "Rebase",
- "isOptional": false,
+ "out": {
+ "ownedByThis": true
+ }
+ }
+ },
+ "git_rebase_next": {
+ "args": {
+ "operation": {
+ "isReturn": true,
+ "ownedByThis": true
+ }
+ }
+ },
+ "git_rebase_open": {
+ "args": {
+ "out": {
"isSelf": true,
- "isReturn": false
+ "ownedBy": ["repo"]
}
- },
+ }
+ },
+ "git_rebase_operation_byindex": {
"return": {
- "isErrorCode": true
+ "ownedByThis": true
+ }
+ },
+ "git_rebase_operation_current": {
+ "return": {
+ "ownedByThis": true
}
}
}
},
"refdb": {
+ "selfFreeing": true,
"functions": {
"git_refdb_backend_fs": {
"ignore": true
},
+ "git_refdb_free": {
+ "ignore": true
+ },
"git_refdb_init_backend": {
"ignore": true
},
@@ -2037,6 +2492,13 @@
},
"git_refdb_new": {
"ignore": true
+ },
+ "git_refdb_open": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
}
}
},
@@ -2046,6 +2508,10 @@
"reference": {
"cppClassName": "GitRefs",
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_reference_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_reference__alloc": {
"ignore": true
@@ -2123,7 +2589,23 @@
"ignore": true
},
"reflog": {
+ "selfFreeing": true,
"functions": {
+ "git_reflog_entry_byindex": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
+ "git_reflog_free": {
+ "ignore": true
+ },
+ "git_reflog_read": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
+ },
"git_reflog_write": {
"isAsync": true,
"isSelf": true,
@@ -2135,6 +2617,11 @@
},
"reflog_entry": {
"functions": {
+ "git_reflog_entry_committer": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
"git_reflog_entry_id_new": {
"return": {
"ownedByThis": true
@@ -2148,12 +2635,24 @@
}
},
"refspec": {
+ "selfFreeing": true,
"cType": "git_refspec",
"functions": {
- "git_refspec_rtransform": {
+ "git_refspec_free": {
"ignore": true
},
- "git_refspec_string": {
+ "git_refspec_parse": {
+ "isAsync": true,
+ "args": {
+ "refspec": {
+ "isReturn": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_refspec_rtransform": {
"ignore": true
},
"git_refspec_transform": {
@@ -2168,6 +2667,10 @@
],
"cType": "git_remote",
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_remote_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_remote_create": {
"isAsync": true,
@@ -2175,6 +2678,14 @@
"isErrorCode": true
}
},
+ "git_remote_create_detached": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "selfOwned": true
+ }
+ }
+ },
"git_remote_connect": {
"isAsync": true,
"return": {
@@ -2231,6 +2742,9 @@
"isErrorCode": true
}
},
+ "git_remote_free": {
+ "ignore": true
+ },
"git_remote_get_fetch_refspecs": {
"args": {
"array": {
@@ -2268,6 +2782,9 @@
"ownedByThis": true
}
},
+ "git_remote_init_callbacks": {
+ "ignore": true
+ },
"git_remote_list": {
"args": {
"out": {
@@ -2340,10 +2857,22 @@
"selfFreeing": true
},
"repository": {
+ "selfFreeing": true,
+ "isSingleton": true,
"dependencies": [
"git2/sys/repository.h"
],
"functions": {
+ "git_repository_config": {
+ "args": {
+ "out": {
+ "ownedByThis": true
+ }
+ }
+ },
+ "git_repository_config_snapshot": {
+ "ignore": true
+ },
"git_repository_discover": {
"isAsync": true,
"return": {
@@ -2357,21 +2886,24 @@
}
}
},
- "git_repository_init_init_options": {
- "ignore": true
- },
"git_repository_fetchhead_foreach": {
"isAsync": true,
"return": {
"isErrorCode": true
}
},
+ "git_repository_free": {
+ "ignore": true
+ },
"git_repository_hashfile": {
"ignore": true
},
"git_repository_ident": {
"ignore": true
},
+ "git_repository_init_init_options": {
+ "ignore": true
+ },
"git_repository_mergehead_foreach": {
"isAsync": true,
"return": {
@@ -2384,6 +2916,34 @@
"git_repository_new": {
"ignore": true
},
+ "git_repository_odb": {
+ "isAsync": true,
+ "args": {
+ "odb": {
+ "ownedByThis": true
+ },
+ "repo": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
+ "git_repository_refdb": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedByThis": true
+ },
+ "repo": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
+ }
+ },
"git_repository_reinit_filesystem": {
"ignore": true
},
@@ -2498,6 +3058,10 @@
},
"revwalk": {
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_revwalk_repository",
+ "singletonCppClassName": "GitRepository"
+ },
"dependencies": [
"../include/commit.h",
"../include/functions/copy.h"
@@ -2506,16 +3070,26 @@
"git_revwalk_add_hide_cb": {
"ignore": true
},
+ "git_revwalk_free": {
+ "ignore": true
+ },
"git_revwalk_new": {
"isAsync": false
}
}
},
"signature": {
+ "selfFreeing": true,
"dupFunction": "git_signature_dup",
"functions": {
"git_signature_default": {
"isAsync": false
+ },
+ "git_signature_dup": {
+ "ignore": true
+ },
+ "git_signature_free": {
+ "ignore": true
},
"git_signature_new": {
"isAsync": false
@@ -2561,6 +3135,9 @@
"isErrorCode": true
}
},
+ "git_stash_apply_init_options": {
+ "ignore": true
+ },
"git_stash_pop": {
"isAsync": true,
"return": {
@@ -2586,7 +3163,10 @@
],
"functions": {
"git_status_byindex": {
- "isAsync": false
+ "isAsync": false,
+ "return": {
+ "ownedBy": ["statuslist"]
+ }
},
"git_status_file": {
"isAsync": true,
@@ -2618,10 +3198,17 @@
}
},
"status_list": {
+ "selfFreeing": true,
"functions": {
+ "git_status_list_free": {
+ "ignore": true
+ },
"git_status_list_new": {
"isAsync": true,
"args": {
+ "out": {
+ "ownedBy": ["repo"]
+ },
"opts": {
"isOptional": true
}
@@ -2633,6 +3220,12 @@
}
},
"strarray": {
+ "selfFreeing": true,
+ "functions": {
+ "git_strarray_free": {
+ "ignore": true
+ }
+ },
"dependencies": [
"../include/str_array_converter.h"
]
@@ -2644,6 +3237,11 @@
]
},
"submodule": {
+ "selfFreeing": true,
+ "ownerFn": {
+ "name": "git_submodule_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_submodule_add_to_index": {
"isAsync": true,
@@ -2682,6 +3280,9 @@
"type": "int"
}
},
+ "git_submodule_free": {
+ "ignore": true
+ },
"git_submodule_index_id": {
"return": {
"ownedByThis": true
@@ -2780,6 +3381,9 @@
"return": {
"isErrorCode": true
}
+ },
+ "git_submodule_update_init_options": {
+ "ignore": true
}
}
},
@@ -2788,11 +3392,12 @@
"../include/str_array_converter.h"
],
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_tag_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
- "git_tag_foreach": {
- "ignore": true
- },
- "git_tag_create": {
+ "git_tag_annotation_create": {
"args": {
"oid": {
"isReturn": true
@@ -2803,15 +3408,7 @@
},
"isAsync": true
},
- "git_tag_create_frombuffer": {
- "ignore": true
- },
- "git_tag_id": {
- "return": {
- "ownedByThis": true
- }
- },
- "git_tag_create_lightweight": {
+ "git_tag_create": {
"args": {
"oid": {
"isReturn": true
@@ -2822,7 +3419,10 @@
},
"isAsync": true
},
- "git_tag_annotation_create": {
+ "git_tag_create_frombuffer": {
+ "ignore": true
+ },
+ "git_tag_create_lightweight": {
"args": {
"oid": {
"isReturn": true
@@ -2833,6 +3433,17 @@
},
"isAsync": true
},
+ "git_tag_foreach": {
+ "ignore": true
+ },
+ "git_tag_free": {
+ "ignore": true
+ },
+ "git_tag_id": {
+ "return": {
+ "ownedByThis": true
+ }
+ },
"git_tag_list": {
"args": {
"tag_names": {
@@ -2928,6 +3539,21 @@
}
}
},
+ "transaction": {
+ "selfFreeing": true,
+ "functions": {
+ "git_transaction_free": {
+ "ignore": true
+ },
+ "git_transaction_new": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
+ }
+ }
+ },
"transfer_progress": {
"dupFunction": "git_transfer_progress_dup"
},
@@ -2938,6 +3564,9 @@
"git_transport_dummy": {
"ignore": true
},
+ "git_transport_init": {
+ "ignore": true
+ },
"git_transport_local": {
"ignore": true
},
@@ -2949,6 +3578,12 @@
},
"git_transport_smart": {
"ignore": true
+ },
+ "git_transport_ssh_with_paths": {
+ "ignore": true
+ },
+ "git_transport_unregister": {
+ "ignore": true
}
},
"cDependencies": [
@@ -2957,30 +3592,48 @@
},
"tree": {
"selfFreeing": true,
+ "ownerFn": {
+ "name": "git_tree_owner",
+ "singletonCppClassName": "GitRepository"
+ },
"functions": {
"git_tree_entry_byid": {
"return": {
- "ownedByThis": true,
- "selfFreeing": false
+ "ownedByThis": true
}
},
"git_tree_entry_byindex": {
"jsFunctionName": "_entryByIndex",
"return": {
- "ownedByThis": true,
- "selfFreeing": false
+ "ownedByThis": true
}
},
"git_tree_entry_byname": {
"jsFunctionName": "_entryByName",
"return": {
- "ownedByThis": true,
- "selfFreeing": false
+ "ownedByThis": true
+ }
+ },
+ "git_tree_entry_bypath": {
+ "isAsync": true,
+ "args": {
+ "out": {
+ "ownedByThis": true
+ },
+ "root": {
+ "isSelf": true
+ }
+ },
+ "return": {
+ "isErrorCode": true
}
},
"git_tree_entrycount": {
"jsFunctionName": "entryCount"
},
+ "git_tree_free": {
+ "ignore": true
+ },
"git_tree_id": {
"return": {
"ownedByThis": true
@@ -2992,13 +3645,16 @@
}
},
"treebuilder": {
+ "selfFreeing": true,
"functions": {
"git_treebuilder_filter": {
"ignore": true
},
+ "git_treebuilder_free": {
+ "ignore": true
+ },
"git_treebuilder_get": {
"return": {
- "selfFreeing": false,
"ownedByThis": true
}
},
@@ -3027,6 +3683,9 @@
},
"git_treebuilder_new": {
"args": {
+ "out": {
+ "ownedBy": ["repo"]
+ },
"source": {
"isOptional": true
}
@@ -3039,6 +3698,12 @@
"dupFunction": "git_tree_entry_dup",
"freeFunctionName": "git_tree_entry_free",
"functions": {
+ "git_tree_entry_dup": {
+ "ignore": true
+ },
+ "git_tree_entry_free": {
+ "ignore": true
+ },
"git_tree_entry_id": {
"return": {
"ownedByThis": true
@@ -3062,12 +3727,33 @@
"cType": "git_worktree",
"freeFunctionName": "git_worktree_free",
"functions": {
- "git_worktree_free": {
- "ignore": true
+ "git_worktree_add": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
},
"git_worktree_add_init_options": {
"ignore": true
},
+ "git_worktree_free": {
+ "ignore": true
+ },
+ "git_worktree_lookup": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
+ },
+ "git_worktree_open_from_repository": {
+ "args": {
+ "out": {
+ "ownedBy": ["repo"]
+ }
+ }
+ },
"git_worktree_prune_init_options": {
"ignore": true
}
diff --git a/generate/input/libgit2-supplement.json b/generate/input/libgit2-supplement.json
index e1fb11d3b..3697a3485 100644
--- a/generate/input/libgit2-supplement.json
+++ b/generate/input/libgit2-supplement.json
@@ -110,6 +110,13 @@
},
"group": "branch"
},
+ "git_clone": {
+ "isManual": true,
+ "cFile": "generate/templates/manual/clone/clone.cc",
+ "isAsync": true,
+ "isPrototypeMethod": false,
+ "group": "clone"
+ },
"git_commit_extract_signature": {
"args": [
{
@@ -144,6 +151,13 @@
"isErrorCode": true
}
},
+ "git_filter_list_load": {
+ "isManual": true,
+ "cFile": "generate/templates/manual/filter_list/load.cc",
+ "isAsync": true,
+ "isPrototypeMethod": false,
+ "group": "filter_list"
+ },
"git_patch_convenient_from_diff": {
"args": [
{
@@ -331,6 +345,16 @@
"git_annotated_commit_lookup"
]
],
+ [
+ "diff_stats",
+ [
+ "git_diff_stats_files_changed",
+ "git_diff_stats_insertions",
+ "git_diff_stats_deletions",
+ "git_diff_stats_to_buf",
+ "git_diff_stats_free"
+ ]
+ ],
[
"filter_list",
[
@@ -352,6 +376,12 @@
"git_filter_source_flags"
]
],
+ [
+ "merge_file_result",
+ [
+ "git_merge_file_result_free"
+ ]
+ ],
[
"odb_object",
[
@@ -363,12 +393,40 @@
"git_odb_object_type"
]
],
+ [
+ "odb_stream",
+ [
+ "git_odb_stream_finalize_write",
+ "git_odb_stream_free",
+ "git_odb_stream_read",
+ "git_odb_stream_write"
+ ]
+ ],
+ [
+ "oid_shorten",
+ [
+ "git_oid_shorten_add",
+ "git_oid_shorten_free",
+ "git_oid_shorten_new"
+ ]
+ ],
[
"patch",
[
"git_patch_convenient_from_diff"
]
],
+ [
+ "pathspec_match_list",
+ [
+ "git_pathspec_match_list_diff_entry",
+ "git_pathspec_match_list_entry",
+ "git_pathspec_match_list_entrycount",
+ "git_pathspec_match_list_failed_entry",
+ "git_pathspec_match_list_failed_entrycount",
+ "git_pathspec_match_list_free"
+ ]
+ ],
[
"reflog_entry",
[
@@ -486,6 +544,72 @@
]
}
],
+ [
+ "git_describe_format_options",
+ {
+ "type": "struct",
+ "fields": [
+ {
+ "type": "unsigned int",
+ "name": "version"
+ },
+ {
+ "type": "unsigned int",
+ "name": "abbreviated_size"
+ },
+ {
+ "type": "int",
+ "name": "always_use_long_format"
+ },
+ {
+ "type": "const char *",
+ "name": "dirty_suffix"
+ }
+ ],
+ "used": {
+ "needs": [
+ "git_describe_init_format_options"
+ ]
+ }
+ }
+ ],
+ [
+ "git_describe_options",
+ {
+ "type": "struct",
+ "fields": [
+ {
+ "type": "unsigned int",
+ "name": "version"
+ },
+ {
+ "type": "unsigned int",
+ "name": "max_candidates_tags"
+ },
+ {
+ "type": "unsigned int",
+ "name": "describe_strategy"
+ },
+ {
+ "type": "const char *",
+ "name": "pattern"
+ },
+ {
+ "type": "int",
+ "name": "only_follow_first_parent"
+ },
+ {
+ "type": "int",
+ "name": "show_commit_oid_as_fallback"
+ }
+ ],
+ "used": {
+ "needs": [
+ "git_describe_init_options"
+ ]
+ }
+ }
+ ],
[
"git_filter",
{
@@ -902,23 +1026,25 @@
"git_annotated_commit_lookup"
]
},
- "filter": {
+ "diff": {
"functions": [
- "git_filter_list_new",
- "git_filter_list_push",
- "git_filter_list_stream_blob",
- "git_filter_list_stream_data",
- "git_filter_list_stream_file",
- "git_filter_source_filemode",
- "git_filter_source_flags",
- "git_filter_source_id",
- "git_filter_source_mode",
- "git_filter_source_path",
- "git_filter_source_repo"
+ "git_diff_stats_files_changed",
+ "git_diff_stats_insertions",
+ "git_diff_stats_deletions",
+ "git_diff_stats_to_buf",
+ "git_diff_stats_free"
]
},
"merge": {
"functions": [
+ "git_merge_driver_lookup",
+ "git_merge_driver_register",
+ "git_merge_driver_source_ancestor",
+ "git_merge_driver_source_ours",
+ "git_merge_driver_source_repo",
+ "git_merge_driver_source_theirs",
+ "git_merge_driver_unregister",
+ "git_merge_file_result_free",
"git_merge_head_free",
"git_merge_head_from_fetchhead",
"git_merge_head_from_id",
@@ -938,7 +1064,28 @@
"git_odb_object_free",
"git_odb_object_id",
"git_odb_object_size",
- "git_odb_object_type"
+ "git_odb_object_type",
+ "git_odb_stream_finalize_write",
+ "git_odb_stream_free",
+ "git_odb_stream_read",
+ "git_odb_stream_write"
+ ]
+ },
+ "oid": {
+ "functions": [
+ "git_oid_shorten_add",
+ "git_oid_shorten_free",
+ "git_oid_shorten_new"
+ ]
+ },
+ "pathspec": {
+ "functions": [
+ "git_pathspec_match_list_diff_entry",
+ "git_pathspec_match_list_entry",
+ "git_pathspec_match_list_entrycount",
+ "git_pathspec_match_list_failed_entry",
+ "git_pathspec_match_list_failed_entrycount",
+ "git_pathspec_match_list_free"
]
},
"reflog": {
@@ -959,6 +1106,7 @@
},
"tree": {
"functions": [
+ "git_tree_entry_dup",
"git_tree_entry_filemode",
"git_tree_entry_filemode_raw",
"git_tree_entry_free",
diff --git a/generate/templates/filters/fields_info.js b/generate/templates/filters/fields_info.js
index 8ec8a930b..7e1e1211b 100644
--- a/generate/templates/filters/fields_info.js
+++ b/generate/templates/filters/fields_info.js
@@ -9,6 +9,7 @@ module.exports = function(fields) {
fieldInfo.parsedName = field.name || "result";
fieldInfo.isCppClassIntType = ~["Uint32", "Int32"].indexOf(field.cppClassName);
fieldInfo.parsedClassName = (field.cppClassName || '').toLowerCase() + "_t";
+ fieldInfo.hasOwner = !fieldInfo.selfOwned && !!fieldInfo.ownedByThis;
result.push(fieldInfo);
});
diff --git a/generate/templates/filters/returns_info.js b/generate/templates/filters/returns_info.js
index 7eaf26e7a..2d178e2c1 100644
--- a/generate/templates/filters/returns_info.js
+++ b/generate/templates/filters/returns_info.js
@@ -4,6 +4,22 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
var result = [];
var args = fn.args || [];
+ // We will use this to figure out the index
+ // of arguments, because sync functions
+ // need to respect ownership to an arbitrary
+ // parameter that is labeled by name in the
+ // descriptor, and we won't have access to
+ // any sort of string to argument index
+ // in the template.
+ var nameToArgIndex = {};
+ var thisArgName = '';
+ args.forEach(function (arg, index) {
+ nameToArgIndex[arg.name] = index;
+ if (arg.isSelf) {
+ thisArgName = arg.name;
+ }
+ });
+
args.forEach(function (arg) {
if (!arg.isReturn) return;
@@ -11,6 +27,7 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
return_info.__proto__ = arg;
+ return_info.isAsync = isAsync;
return_info.parsedName = isAsync ? "baton->" + return_info.name : return_info.name;
return_info.isCppClassIntType = ~['Uint32', 'Int32'].indexOf(return_info.cppClassName);
return_info.needsDereference
@@ -21,6 +38,23 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
return_info.returnNameOrName = return_info.returnName || return_info.name;
return_info.jsOrCppClassName = return_info.jsClassName || return_info.cppClassName;
return_info.isOutParam = true;
+ return_info.hasOwner = !return_info.selfOwned &&
+ !!(return_info.ownedBy || return_info.ownedByThis || return_info.ownerFn);
+ return_info.ownedByIndices = [];
+
+ if (isAsync && return_info.ownedByThis) {
+ return_info.ownedBy = return_info.ownedBy || [];
+ return_info.ownedBy.unshift(thisArgName);
+ }
+
+ // Here we convert ownedBy, which is the list of parameter names
+ // that own this result to the argument index.
+ // sync functions will need to know this.
+ if (!isAsync && return_info.ownedBy) {
+ return_info.ownedBy.forEach(function (argName) {
+ return_info.ownedByIndices.push(nameToArgIndex[return_info.ownedBy]);
+ })
+ }
result.push(return_info);
});
@@ -33,6 +67,23 @@ module.exports = function(fn, argReturnsOnly, isAsync) {
var return_info = {};
return_info.__proto__ = fn.return;
+
+ return_info.isAsync = isAsync;
+ return_info.hasOwner = !return_info.selfOwned &&
+ !!(return_info.ownedBy || return_info.ownedByThis || return_info.ownerFn);
+ return_info.ownedByIndices = [];
+ return_info.ownedBy = return_info.ownedBy || [];
+
+ if (return_info.ownedByThis && isAsync) {
+ return_info.ownedBy.push(thisArgName);
+ }
+
+ if (!isAsync) {
+ return_info.ownedByIndices = return_info.ownedBy.map(function (ownerName) {
+ return nameToArgIndex[ownerName];
+ });
+ }
+
return_info.parsedName = return_info.name && isAsync ? "baton->" + return_info.name : "result";
return_info.isCppClassIntType = ~['Uint32', 'Int32'].indexOf(return_info.cppClassName);
return_info.parsedClassName = (return_info.cppClassName || '').toLowerCase() + "_t";
diff --git a/generate/templates/manual/clone/clone.cc b/generate/templates/manual/clone/clone.cc
new file mode 100644
index 000000000..7ddcd559b
--- /dev/null
+++ b/generate/templates/manual/clone/clone.cc
@@ -0,0 +1,211 @@
+// NOTE you may need to occasionally rebuild this method by calling the generators
+// if major changes are made to the templates / generator.
+
+// Due to some file locking issues, we have the need to free a repository after it's cloned.
+// We do not expose free functions to javascript, and so, we've moved the implementation of
+// cloning, freeing the repo, and opening the repo into a custom template.
+
+/*
+ * @param String url
+ * @param String local_path
+ * @param CloneOptions options
+ * @param Repository callback
+ */
+NAN_METHOD(GitClone::Clone) {
+
+ if (info.Length() == 0 || !info[0]->IsString()) {
+ return Nan::ThrowError("String url is required.");
+ }
+
+ if (info.Length() == 1 || !info[1]->IsString()) {
+ return Nan::ThrowError("String local_path is required.");
+ }
+
+ if (info.Length() == 3 || !info[3]->IsFunction()) {
+ return Nan::ThrowError("Callback is required and must be a Function.");
+ }
+
+ CloneBaton *baton = new CloneBaton;
+
+ baton->error_code = GIT_OK;
+ baton->error = NULL;
+
+ // start convert_from_v8 block
+ const char *from_url = NULL;
+
+ String::Utf8Value url(info[0]->ToString());
+ // malloc with one extra byte so we can add the terminating null character
+ // C-strings expect:
+ from_url = (const char *)malloc(url.length() + 1);
+ // copy the characters from the nodejs string into our C-string (used instead
+ // of strdup or strcpy because nulls in the middle of strings are valid coming
+ // from nodejs):
+ memcpy((void *)from_url, *url, url.length());
+ // ensure the final byte of our new string is null, extra casts added to
+ // ensure compatibility with various C types used in the nodejs binding
+ // generation:
+ memset((void *)(((char *)from_url) + url.length()), 0, 1);
+ // end convert_from_v8 block
+ baton->url = from_url;
+ // start convert_from_v8 block
+ const char *from_local_path = NULL;
+
+ String::Utf8Value local_path(info[1]->ToString());
+ // malloc with one extra byte so we can add the terminating null character
+ // C-strings expect:
+ from_local_path = (const char *)malloc(local_path.length() + 1);
+ // copy the characters from the nodejs string into our C-string (used instead
+ // of strdup or strcpy because nulls in the middle of strings are valid coming
+ // from nodejs):
+ memcpy((void *)from_local_path, *local_path, local_path.length());
+ // ensure the final byte of our new string is null, extra casts added to
+ // ensure compatibility with various C types used in the nodejs binding
+ // generation:
+ memset((void *)(((char *)from_local_path) + local_path.length()), 0, 1);
+ // end convert_from_v8 block
+ baton->local_path = from_local_path;
+ // start convert_from_v8 block
+ const git_clone_options *from_options = NULL;
+ if (info[2]->IsObject()) {
+ from_options = Nan::ObjectWrap::Unwrap(info[2]->ToObject())
+ ->GetValue();
+ } else {
+ from_options = 0;
+ }
+ // end convert_from_v8 block
+ baton->options = from_options;
+
+ Nan::Callback *callback =
+ new Nan::Callback(v8::Local::Cast(info[3]));
+ CloneWorker *worker = new CloneWorker(baton, callback);
+
+ if (!info[0]->IsUndefined() && !info[0]->IsNull())
+ worker->SaveToPersistent("url", info[0]->ToObject());
+ if (!info[1]->IsUndefined() && !info[1]->IsNull())
+ worker->SaveToPersistent("local_path", info[1]->ToObject());
+ if (!info[2]->IsUndefined() && !info[2]->IsNull())
+ worker->SaveToPersistent("options", info[2]->ToObject());
+
+ AsyncLibgit2QueueWorker(worker);
+ return;
+}
+
+void GitClone::CloneWorker::Execute() {
+ giterr_clear();
+
+ {
+ LockMaster lockMaster(
+ /*asyncAction: */ true, baton->url, baton->local_path, baton->options);
+
+ git_repository *repo;
+ int result =
+ git_clone(&repo, baton->url, baton->local_path, baton->options);
+
+ if (result == GIT_OK) {
+ // This is required to clean up after the clone to avoid file locking
+ // issues in Windows and potentially other issues we don't know about.
+ git_repository_free(repo);
+
+ // We want to provide a valid repository object, so reopen the repository
+ // after clone and cleanup.
+ result = git_repository_open(&baton->out, baton->local_path);
+ }
+
+ baton->error_code = result;
+
+ if (result != GIT_OK && giterr_last() != NULL) {
+ baton->error = git_error_dup(giterr_last());
+ }
+ }
+}
+
+void GitClone::CloneWorker::HandleOKCallback() {
+ if (baton->error_code == GIT_OK) {
+ v8::Local to;
+ // start convert_to_v8 block
+
+ if (baton->out != NULL) {
+ // GitRepository baton->out
+ to = GitRepository::New(baton->out, true);
+ } else {
+ to = Nan::Null();
+ }
+
+ // end convert_to_v8 block
+ v8::Local result = to;
+
+ v8::Local argv[2] = {Nan::Null(), result};
+ callback->Call(2, argv, async_resource);
+ } else {
+ if (baton->error) {
+ v8::Local err;
+ if (baton->error->message) {
+ err = Nan::Error(baton->error->message)->ToObject();
+ } else {
+ err = Nan::Error("Method clone has thrown an error.")->ToObject();
+ }
+ err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
+ err->Set(Nan::New("errorFunction").ToLocalChecked(),
+ Nan::New("Clone.clone").ToLocalChecked());
+ v8::Local argv[1] = {err};
+ callback->Call(1, argv, async_resource);
+ if (baton->error->message)
+ free((void *)baton->error->message);
+ free((void *)baton->error);
+ } else if (baton->error_code < 0) {
+ std::queue> workerArguments;
+ workerArguments.push(GetFromPersistent("url"));
+ workerArguments.push(GetFromPersistent("local_path"));
+ workerArguments.push(GetFromPersistent("options"));
+ bool callbackFired = false;
+ while (!workerArguments.empty()) {
+ v8::Local node = workerArguments.front();
+ workerArguments.pop();
+
+ if (!node->IsObject() || node->IsArray() || node->IsBooleanObject() ||
+ node->IsDate() || node->IsFunction() || node->IsNumberObject() ||
+ node->IsRegExp() || node->IsStringObject()) {
+ continue;
+ }
+
+ v8::Local nodeObj = node->ToObject();
+ v8::Local checkValue = GetPrivate(
+ nodeObj, Nan::New("NodeGitPromiseError").ToLocalChecked());
+
+ if (!checkValue.IsEmpty() && !checkValue->IsNull() &&
+ !checkValue->IsUndefined()) {
+ v8::Local argv[1] = {checkValue->ToObject()};
+ callback->Call(1, argv, async_resource);
+ callbackFired = true;
+ break;
+ }
+
+ v8::Local properties = nodeObj->GetPropertyNames();
+ for (unsigned int propIndex = 0; propIndex < properties->Length();
+ ++propIndex) {
+ v8::Local propName =
+ properties->Get(propIndex)->ToString();
+ v8::Local nodeToQueue = nodeObj->Get(propName);
+ if (!nodeToQueue->IsUndefined()) {
+ workerArguments.push(nodeToQueue);
+ }
+ }
+ }
+
+ if (!callbackFired) {
+ v8::Local err =
+ Nan::Error("Method clone has thrown an error.")->ToObject();
+ err->Set(Nan::New("errno").ToLocalChecked(),
+ Nan::New(baton->error_code));
+ err->Set(Nan::New("errorFunction").ToLocalChecked(),
+ Nan::New("Clone.clone").ToLocalChecked());
+ v8::Local argv[1] = {err};
+ callback->Call(1, argv, async_resource);
+ }
+ } else {
+ callback->Call(0, NULL, async_resource);
+ }
+ }
+
+ delete baton;
+}
diff --git a/generate/templates/manual/filter_list/load.cc b/generate/templates/manual/filter_list/load.cc
new file mode 100644
index 000000000..1e7788e65
--- /dev/null
+++ b/generate/templates/manual/filter_list/load.cc
@@ -0,0 +1,245 @@
+// NOTE you may need to occasionally rebuild this method by calling the generators
+// if major changes are made to the templates / generator.
+
+// git_filter_list_load has a more complex ownership pattern than is currently available
+// in the generator. This is because it not only has to get the repo as an owner,
+// but it also needs to discover which custom filters, a git_filter, it is bound to, if any.
+// We must enforce that the custom filters are not freed before a git_filter_list is freed,
+// but a git_filter_list also has pointers to the repo in it.
+
+// TODO In the future, it would be awesome if we could instead of writing a manual method like this, provide
+// custom ownership methods that can be injected into the HandleOKCallback.
+
+/*
+ * @param Repository repo
+ * @param Blob blob
+ * @param String path
+ * @param Number mode
+ * @param Number flags
+ * @param FilterList callback
+ */
+NAN_METHOD(GitFilterList::Load) {
+ if (info.Length() == 0 || !info[0]->IsObject()) {
+ return Nan::ThrowError("Repository repo is required.");
+ }
+
+ if (info.Length() == 2 || !info[2]->IsString()) {
+ return Nan::ThrowError("String path is required.");
+ }
+
+ if (info.Length() == 3 || !info[3]->IsNumber()) {
+ return Nan::ThrowError("Number mode is required.");
+ }
+
+ if (info.Length() == 4 || !info[4]->IsNumber()) {
+ return Nan::ThrowError("Number flags is required.");
+ }
+
+ if (info.Length() == 5 || !info[5]->IsFunction()) {
+ return Nan::ThrowError("Callback is required and must be a Function.");
+ }
+
+ LoadBaton *baton = new LoadBaton;
+
+ baton->error_code = GIT_OK;
+ baton->error = NULL;
+
+ // start convert_from_v8 block
+ git_repository *from_repo = NULL;
+ from_repo =
+ Nan::ObjectWrap::Unwrap(info[0]->ToObject())->GetValue();
+ // end convert_from_v8 block
+ baton->repo = from_repo;
+ // start convert_from_v8 block
+ git_blob *from_blob = NULL;
+ if (info[1]->IsObject()) {
+ from_blob =
+ Nan::ObjectWrap::Unwrap(info[1]->ToObject())->GetValue();
+ } else {
+ from_blob = 0;
+ }
+ // end convert_from_v8 block
+ baton->blob = from_blob;
+ // start convert_from_v8 block
+ const char *from_path = NULL;
+
+ String::Utf8Value path(info[2]->ToString());
+ // malloc with one extra byte so we can add the terminating null character
+ // C-strings expect:
+ from_path = (const char *)malloc(path.length() + 1);
+ // copy the characters from the nodejs string into our C-string (used instead
+ // of strdup or strcpy because nulls in the middle of strings are valid coming
+ // from nodejs):
+ memcpy((void *)from_path, *path, path.length());
+ // ensure the final byte of our new string is null, extra casts added to
+ // ensure compatibility with various C types used in the nodejs binding
+ // generation:
+ memset((void *)(((char *)from_path) + path.length()), 0, 1);
+ // end convert_from_v8 block
+ baton->path = from_path;
+ // start convert_from_v8 block
+ git_filter_mode_t from_mode;
+ from_mode = (git_filter_mode_t)(int)info[3].As()->Value();
+ // end convert_from_v8 block
+ baton->mode = from_mode;
+ // start convert_from_v8 block
+ uint32_t from_flags;
+ from_flags = (uint32_t)info[4].As()->Value();
+ // end convert_from_v8 block
+ baton->flags = from_flags;
+
+ Nan::Callback *callback =
+ new Nan::Callback(v8::Local::Cast(info[5]));
+ LoadWorker *worker = new LoadWorker(baton, callback);
+
+ if (!info[0]->IsUndefined() && !info[0]->IsNull())
+ worker->SaveToPersistent("repo", info[0]->ToObject());
+ if (!info[1]->IsUndefined() && !info[1]->IsNull())
+ worker->SaveToPersistent("blob", info[1]->ToObject());
+ if (!info[2]->IsUndefined() && !info[2]->IsNull())
+ worker->SaveToPersistent("path", info[2]->ToObject());
+ if (!info[3]->IsUndefined() && !info[3]->IsNull())
+ worker->SaveToPersistent("mode", info[3]->ToObject());
+ if (!info[4]->IsUndefined() && !info[4]->IsNull())
+ worker->SaveToPersistent("flags", info[4]->ToObject());
+
+ AsyncLibgit2QueueWorker(worker);
+ return;
+}
+
+void GitFilterList::LoadWorker::Execute() {
+ giterr_clear();
+
+ {
+ LockMaster lockMaster(
+ /*asyncAction: */ true, baton->repo, baton->blob, baton->path);
+
+ int result = git_filter_list_load(&baton->filters, baton->repo, baton->blob,
+ baton->path, baton->mode, baton->flags);
+
+ baton->error_code = result;
+
+ if (result != GIT_OK && giterr_last() != NULL) {
+ baton->error = git_error_dup(giterr_last());
+ }
+ }
+}
+
+void GitFilterList::LoadWorker::HandleOKCallback() {
+ if (baton->error_code == GIT_OK) {
+ v8::Local to;
+ // start convert_to_v8 block
+
+ if (baton->filters != NULL) {
+ // GitFilterList baton->filters
+ v8::Local owners = Nan::New(0);
+ v8::Local filterRegistry = Nan::New(GitFilterRegistry::persistentHandle);
+ v8::Local propertyNames = filterRegistry->GetPropertyNames();
+
+ Nan::Set(
+ owners,
+ Nan::New(0),
+ this->GetFromPersistent("repo")->ToObject()
+ );
+
+ for (uint32_t index = 0; index < propertyNames->Length(); ++index) {
+ v8::Local propertyName = propertyNames->Get(index)->ToString();
+ String::Utf8Value propertyNameAsUtf8Value(propertyName);
+ const char *propertyNameAsCString = *propertyNameAsUtf8Value;
+
+ bool isNotMethodOnRegistry = strcmp("register", propertyNameAsCString)
+ && strcmp("unregister", propertyNameAsCString);
+ if (isNotMethodOnRegistry && git_filter_list_contains(baton->filters, propertyNameAsCString)) {
+ Nan::Set(
+ owners,
+ Nan::New(owners->Length()),
+ filterRegistry->Get(propertyName)
+ );
+ }
+ }
+
+ to = GitFilterList::New(baton->filters, true, owners->ToObject());
+ } else {
+ to = Nan::Null();
+ }
+
+ // end convert_to_v8 block
+ v8::Local result = to;
+
+ v8::Local argv[2] = {Nan::Null(), result};
+ callback->Call(2, argv, async_resource);
+ } else {
+ if (baton->error) {
+ v8::Local err;
+ if (baton->error->message) {
+ err = Nan::Error(baton->error->message)->ToObject();
+ } else {
+ err = Nan::Error("Method load has thrown an error.")->ToObject();
+ }
+ err->Set(Nan::New("errno").ToLocalChecked(), Nan::New(baton->error_code));
+ err->Set(Nan::New("errorFunction").ToLocalChecked(),
+ Nan::New("FilterList.load").ToLocalChecked());
+ v8::Local argv[1] = {err};
+ callback->Call(1, argv, async_resource);
+ if (baton->error->message)
+ free((void *)baton->error->message);
+ free((void *)baton->error);
+ } else if (baton->error_code < 0) {
+ std::queue> workerArguments;
+ workerArguments.push(GetFromPersistent("repo"));
+ workerArguments.push(GetFromPersistent("blob"));
+ workerArguments.push(GetFromPersistent("path"));
+ workerArguments.push(GetFromPersistent("mode"));
+ workerArguments.push(GetFromPersistent("flags"));
+ bool callbackFired = false;
+ while (!workerArguments.empty()) {
+ v8::Local node = workerArguments.front();
+ workerArguments.pop();
+
+ if (!node->IsObject() || node->IsArray() || node->IsBooleanObject() ||
+ node->IsDate() || node->IsFunction() || node->IsNumberObject() ||
+ node->IsRegExp() || node->IsStringObject()) {
+ continue;
+ }
+
+ v8::Local nodeObj = node->ToObject();
+ v8::Local checkValue = GetPrivate(
+ nodeObj, Nan::New("NodeGitPromiseError").ToLocalChecked());
+
+ if (!checkValue.IsEmpty() && !checkValue->IsNull() &&
+ !checkValue->IsUndefined()) {
+ v8::Local argv[1] = {checkValue->ToObject()};
+ callback->Call(1, argv, async_resource);
+ callbackFired = true;
+ break;
+ }
+
+ v8::Local properties = nodeObj->GetPropertyNames();
+ for (unsigned int propIndex = 0; propIndex < properties->Length();
+ ++propIndex) {
+ v8::Local propName =
+ properties->Get(propIndex)->ToString();
+ v8::Local nodeToQueue = nodeObj->Get(propName);
+ if (!nodeToQueue->IsUndefined()) {
+ workerArguments.push(nodeToQueue);
+ }
+ }
+ }
+
+ if (!callbackFired) {
+ v8::Local err =
+ Nan::Error("Method load has thrown an error.")->ToObject();
+ err->Set(Nan::New("errno").ToLocalChecked(),
+ Nan::New(baton->error_code));
+ err->Set(Nan::New("errorFunction").ToLocalChecked(),
+ Nan::New("FilterList.load").ToLocalChecked());
+ v8::Local argv[1] = {err};
+ callback->Call(1, argv, async_resource);
+ }
+ } else {
+ callback->Call(0, NULL, async_resource);
+ }
+ }
+
+ delete baton;
+}
diff --git a/generate/templates/manual/include/nodegit_wrapper.h b/generate/templates/manual/include/nodegit_wrapper.h
index ea5277a50..c40b7af1d 100644
--- a/generate/templates/manual/include/nodegit_wrapper.h
+++ b/generate/templates/manual/include/nodegit_wrapper.h
@@ -2,6 +2,7 @@
#define NODEGIT_WRAPPER_H
#include
+#include
// the Traits template parameter supplies:
// typename cppClass - the C++ type of the NodeGit wrapper (e.g. GitRepository)
diff --git a/generate/templates/manual/include/reference_counter.h b/generate/templates/manual/include/reference_counter.h
new file mode 100644
index 000000000..2afa2310c
--- /dev/null
+++ b/generate/templates/manual/include/reference_counter.h
@@ -0,0 +1,30 @@
+#ifndef REFERENCE_COUNTER_H
+#define REFERENCE_COUNTER_H
+
+#include
+
+#include "lock_master.h"
+
+// There are certain instances in libgit2 which can be retrieved from multiple sources
+// We need to make sure that we're counting how many times we've seen that pointer
+// so that when we are performing free behavior, we don't free it until it is no longer
+// referenced. The main example of this behavior is the repository instance, where
+// after git_repository_open open (first instance) we can git_commit_lookup, followed by
+// git_commit_owner (second instance).
+//
+// I was hoping that we could construct a Persistent handle, but that would interfere with
+// GC. We want it to attmept to GC, and if this handle exists, the final repo will not
+// free itself :(.
+//
+// Make sure to utilize LockMaster when incrementing or decrementing a reference count.
+class ReferenceCounter {
+public:
+ static void incrementCountForPointer(void *ptr);
+
+ static unsigned long decrementCountForPointer(void *ptr);
+
+private:
+ static std::unordered_map referenceCountByPointer;
+};
+
+#endif
diff --git a/generate/templates/manual/src/nodegit_wrapper.cc b/generate/templates/manual/src/nodegit_wrapper.cc
index ea6694425..26ead60da 100644
--- a/generate/templates/manual/src/nodegit_wrapper.cc
+++ b/generate/templates/manual/src/nodegit_wrapper.cc
@@ -1,17 +1,26 @@
template
NodeGitWrapper::NodeGitWrapper(typename Traits::cType *raw, bool selfFreeing, v8::Local owner) {
- if (!owner.IsEmpty()) {
- // if we have an owner, there are two options - either we duplicate the raw object
- // (so we own the duplicate, and can self-free it)
- // or we keep a handle on the owner so it doesn't get garbage collected
- // while this wrapper is accessible
- if(Traits::isDuplicable) {
+ if (Traits::isSingleton) {
+ ReferenceCounter::incrementCountForPointer((void *)raw);
+ this->raw = raw;
+ } else if (!owner.IsEmpty()) {
+ // if we have an owner, it could mean 2 things:
+ // 1. We are borrowed memory from another struct and should not be freed. We will keep a handle to the owner
+ // so that the owner isn't gc'd while we are using its memory.
+ // 2. We are borrowed memory from another struct and can be duplicated, so we should duplicate
+ // and become selfFreeing.
+ // 3. We are cached memory, potentially on the repo or config.
+ // Even though we have a handle in another objects cache, we are expected to call free,
+ // otherwise we are leaking memory. Cached objects are reference counted in libgit2, but will be leaked
+ // even if the cache is cleared if we haven't freed them. We will keep a handle on the owner, even though it
+ // is probably safe as we're reference counted. This should at worst just ensure that the cache owner is the
+ // last thing to be freed, and that is more safety than anything else.
+ if (Traits::isDuplicable) {
Traits::duplicate(&this->raw, raw);
selfFreeing = true;
} else {
this->owner.Reset(owner);
this->raw = raw;
- selfFreeing = false;
}
} else {
this->raw = raw;
@@ -34,7 +43,7 @@ NodeGitWrapper::NodeGitWrapper(const char *error) {
template
NodeGitWrapper::~NodeGitWrapper() {
- if(Traits::isFreeable && selfFreeing) {
+ if (Traits::isFreeable && selfFreeing) {
Traits::free(raw);
SelfFreeingInstanceCount--;
raw = NULL;
diff --git a/generate/templates/manual/src/reference_counter.cc b/generate/templates/manual/src/reference_counter.cc
new file mode 100644
index 000000000..1adc1df4b
--- /dev/null
+++ b/generate/templates/manual/src/reference_counter.cc
@@ -0,0 +1,24 @@
+#include "../include/reference_counter.h"
+
+void ReferenceCounter::incrementCountForPointer(void *ptr) {
+ LockMaster(true, &referenceCountByPointer);
+ if (referenceCountByPointer.find(ptr) == referenceCountByPointer.end()) {
+ referenceCountByPointer[ptr] = 1;
+ } else {
+ referenceCountByPointer[ptr] = referenceCountByPointer[ptr] + 1;
+ }
+}
+
+unsigned long ReferenceCounter::decrementCountForPointer(void *ptr) {
+ LockMaster(true, &referenceCountByPointer);
+ unsigned long referenceCount = referenceCountByPointer[ptr];
+ if (referenceCount == 1) {
+ referenceCountByPointer.erase(ptr);
+ return 0;
+ } else {
+ referenceCountByPointer[ptr] = referenceCount - 1;
+ return referenceCountByPointer[ptr];
+ }
+}
+
+std::unordered_map ReferenceCounter::referenceCountByPointer;
diff --git a/generate/templates/partials/async_function.cc b/generate/templates/partials/async_function.cc
index d82898292..c4cdb115d 100644
--- a/generate/templates/partials/async_function.cc
+++ b/generate/templates/partials/async_function.cc
@@ -13,41 +13,41 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
{%each args|argsInfo as arg %}
{%if arg.globalPayload %}
- {{ cppFunctionName }}_globalPayload* globalPayload = new {{ cppFunctionName }}_globalPayload;
+ {{ cppFunctionName }}_globalPayload* globalPayload = new {{ cppFunctionName }}_globalPayload;
{%endif%}
{%endeach%}
{%each args|argsInfo as arg %}
{%if not arg.isReturn %}
{%if arg.isSelf %}
- baton->{{ arg.name }} = Nan::ObjectWrap::Unwrap<{{ arg.cppClassName }}>(info.This())->GetValue();
+ baton->{{ arg.name }} = Nan::ObjectWrap::Unwrap<{{ arg.cppClassName }}>(info.This())->GetValue();
{%elsif arg.isCallbackFunction %}
- if (!info[{{ arg.jsArg }}]->IsFunction()) {
- baton->{{ arg.name }} = NULL;
+ if (!info[{{ arg.jsArg }}]->IsFunction()) {
+ baton->{{ arg.name }} = NULL;
{%if arg.payload.globalPayload %}
- globalPayload->{{ arg.name }} = NULL;
+ globalPayload->{{ arg.name }} = NULL;
{%else%}
- baton->{{ arg.payload.name }} = NULL;
+ baton->{{ arg.payload.name }} = NULL;
{%endif%}
- }
- else {
- baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback;
- {%if arg.payload.globalPayload %}
- globalPayload->{{ arg.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As());
- {%else%}
- baton->{{ arg.payload.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As());
- {%endif%}
- }
+ }
+ else {
+ baton->{{ arg.name}} = {{ cppFunctionName }}_{{ arg.name }}_cppCallback;
+ {%if arg.payload.globalPayload %}
+ globalPayload->{{ arg.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As());
+ {%else%}
+ baton->{{ arg.payload.name }} = new Nan::Callback(info[{{ arg.jsArg }}].As());
+ {%endif%}
+ }
{%elsif arg.payloadFor %}
{%if arg.globalPayload %}
- baton->{{ arg.name }} = globalPayload;
+ baton->{{ arg.name }} = globalPayload;
{%endif%}
{%elsif arg.name %}
- {%partial convertFromV8 arg%}
+ {%partial convertFromV8 arg%}
{%if not arg.payloadFor %}
- baton->{{ arg.name }} = from_{{ arg.name }};
+ baton->{{ arg.name }} = from_{{ arg.name }};
{%if arg | isOid %}
- baton->{{ arg.name }}NeedsFree = info[{{ arg.jsArg }}]->IsString();
+ baton->{{ arg.name }}NeedsFree = info[{{ arg.jsArg }}]->IsString();
{%endif%}
{%endif%}
{%endif%}
@@ -62,13 +62,14 @@ NAN_METHOD({{ cppClassName }}::{{ cppFunctionName }}) {
Nan::Callback *callback = new Nan::Callback(v8::Local::Cast(info[{{args|jsArgsCount}}]));
{{ cppFunctionName }}Worker *worker = new {{ cppFunctionName }}Worker(baton, callback);
+
{%each args|argsInfo as arg %}
{%if not arg.isReturn %}
{%if arg.isSelf %}
- worker->SaveToPersistent("{{ arg.name }}", info.This());
+ worker->SaveToPersistent("{{ arg.name }}", info.This());
{%elsif not arg.isCallbackFunction %}
- if (!info[{{ arg.jsArg }}]->IsUndefined() && !info[{{ arg.jsArg }}]->IsNull())
- worker->SaveToPersistent("{{ arg.name }}", info[{{ arg.jsArg }}]->ToObject());
+ if (!info[{{ arg.jsArg }}]->IsUndefined() && !info[{{ arg.jsArg }}]->IsNull())
+ worker->SaveToPersistent("{{ arg.name }}", info[{{ arg.jsArg }}]->ToObject());
{%endif%}
{%endif%}
{%endeach%}
@@ -81,41 +82,45 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() {
giterr_clear();
{
- LockMaster lockMaster(/*asyncAction: */true{%each args|argsInfo as arg %}
- {%if arg.cType|isPointer%}{%if not arg.cType|isDoublePointer%}
- ,baton->{{ arg.name }}
- {%endif%}{%endif%}
- {%endeach%});
+ LockMaster lockMaster(
+ /*asyncAction: */true
+ {%each args|argsInfo as arg %}
+ {%if arg.cType|isPointer%}
+ {%if not arg.cType|isDoublePointer%}
+ ,baton->{{ arg.name }}
+ {%endif%}
+ {%endif%}
+ {%endeach%}
+ );
{%if .|hasReturnType %}
- {{ return.cType }} result = {{ cFunctionName }}(
+ {{ return.cType }} result = {{ cFunctionName }}(
{%else%}
- {{ cFunctionName }}(
+ {{ cFunctionName }}(
{%endif%}
{%-- Insert Function Arguments --%}
{%each args|argsInfo as arg %}
{%-- turn the pointer into a ref --%}
- {%if arg.isReturn|and arg.cType|isDoublePointer %}&{%endif%}baton->{{ arg.name }}{%if not arg.lastArg %},{%endif%}
-
+ {%if arg.isReturn|and arg.cType|isDoublePointer %}&{%endif%}baton->{{ arg.name }}{%if not arg.lastArg %},{%endif%}
{%endeach%}
- );
+ );
{%if return.isResultOrError %}
- baton->error_code = result;
- if (result < GIT_OK && giterr_last() != NULL) {
- baton->error = git_error_dup(giterr_last());
- }
+ baton->error_code = result;
+ if (result < GIT_OK && giterr_last() != NULL) {
+ baton->error = git_error_dup(giterr_last());
+ }
{%elsif return.isErrorCode %}
- baton->error_code = result;
+ baton->error_code = result;
- if (result != GIT_OK && giterr_last() != NULL) {
- baton->error = git_error_dup(giterr_last());
- }
+ if (result != GIT_OK && giterr_last() != NULL) {
+ baton->error = git_error_dup(giterr_last());
+ }
{%elsif not return.cType == 'void' %}
- baton->result = result;
+ baton->result = result;
{%endif%}
}
@@ -123,30 +128,32 @@ void {{ cppClassName }}::{{ cppFunctionName }}Worker::Execute() {
void {{ cppClassName }}::{{ cppFunctionName }}Worker::HandleOKCallback() {
{%if return.isResultOrError %}
- if (baton->error_code >= GIT_OK) {
+ if (baton->error_code >= GIT_OK) {
{%else%}
- if (baton->error_code == GIT_OK) {
+ if (baton->error_code == GIT_OK) {
{%endif%}
- {%if return.isResultOrError %}
+
+ {%if return.isResultOrError %}
v8::Local result = Nan::New(baton->error_code);
- {%elsif not .|returnsCount %}
+ {%elsif not .|returnsCount %}
v8::Local result = Nan::Undefined();
- {%else%}
+ {%else%}
v8::Local to;
+ {%if .|returnsCount > 1 %}
+ v8::Local