Skip to content

Commit f4f7a4d

Browse files
committed
Adding Filter registration, clean build, passing test
Build + test register complete filter init test wip
1 parent 4e34797 commit f4f7a4d

6 files changed

Lines changed: 230 additions & 14 deletions

File tree

generate/input/descriptor.json

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -879,6 +879,7 @@
879879
}
880880
},
881881
"filter": {
882+
"selfFreeing": false,
882883
"hasConstructor": true,
883884
"functions": {
884885
"git_filter_list_apply_to_blob": {
@@ -930,6 +931,21 @@
930931
}
931932
}
932933
},
934+
"filter_registry": {
935+
"functions": {
936+
"git_filter_register": {
937+
"jsFunctionName": "register",
938+
"args": {
939+
"filter": {
940+
"isSelf": false
941+
}
942+
}
943+
},
944+
"git_filter_unregister": {
945+
"jsFunctionName": "unregister"
946+
}
947+
}
948+
},
933949
"filter_source": {
934950
"ignore": false,
935951
"cDependencies": [

generate/input/libgit2-supplement.json

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,13 @@
273273
"git_annotated_commit_lookup"
274274
]
275275
],
276+
[
277+
"filter_registry",
278+
[
279+
"git_filter_register",
280+
"git_filter_unregister"
281+
]
282+
],
276283
[
277284
"filter_source",
278285
[
@@ -447,10 +454,6 @@
447454
"type": "git_filter_apply_fn",
448455
"name": "apply"
449456
},
450-
{
451-
"type": "git_filter_stream_fn",
452-
"name": "stream"
453-
},
454457
{
455458
"type": "git_filter_cleanup_fn",
456459
"name": "cleanup"

generate/templates/partials/field_accessors.cc

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,11 @@
195195

196196
v8::Local<Value> argv[{{ field.args|jsArgsCount }}] = {
197197
{% each field.args|argsInfo as arg %}
198-
{% if arg.name == "payload" %}
198+
{% if arg.cppClassName == "String" %}
199199
{% if isExtendedStruct %}
200-
Nan::New((({{cType}}_extended *)instance)->payload),
200+
Nan::New<String>(*baton->{{ arg.name }}).ToLocalChecked(),
201201
{% else %}
202-
{%-- payload is always the last arg --%}
203-
Nan::New(instance->{{ fields|payloadFor field.name }}),
202+
Nan::New(baton->{{ arg.name }}).ToLocalChecked(),
204203
{% endif %}
205204
{% elsif arg.isJsArg %}
206205
{% if arg.isEnum %}
@@ -210,8 +209,13 @@
210209
{% elsif arg.cType == "size_t" %}
211210
// HACK: NAN should really have an overload for Nan::New to support size_t
212211
Nan::New((unsigned int)baton->{{ arg.name }}),
213-
{% elsif arg.cppClassName == 'String' %}
214-
Nan::New(baton->{{ arg.name }}).ToLocalChecked(),
212+
{% elsif arg.name == "payload" %}
213+
{% if isExtendedStruct %}
214+
Nan::New((({{cType}}_extended *)instance)->payload),
215+
{% else %}
216+
{%-- payload is always the last arg --%}
217+
Nan::New(instance->{{ fields|payloadFor field.name }}),
218+
{% endif %}
215219
{% else %}
216220
Nan::New(baton->{{ arg.name }}),
217221
{% endif %}

generate/templates/templates/struct_content.cc

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,15 @@ using namespace std;
3535
{% if ignoreInit == true %}
3636
this->raw = new {{ cType }};
3737
{% else %}
38-
{{ cType }} wrappedValue = {{ cType|upper }}_INIT;
39-
this->raw = ({{ cType }}*) malloc(sizeof({{ cType }}));
40-
memcpy(this->raw, &wrappedValue, sizeof({{ cType }}));
38+
{% if isExtendedStruct %}
39+
{{ cType }}_extended wrappedValue = {{ cType|upper }}_INIT;
40+
this->raw = ({{ cType }}*) malloc(sizeof({{ cType }}_extended));
41+
memcpy(this->raw, &wrappedValue, sizeof({{ cType }}_extended));
42+
{% else %}
43+
{{ cType }} wrappedValue = {{ cType|upper }}_INIT;
44+
this->raw = ({{ cType }}*) malloc(sizeof({{ cType }}));
45+
memcpy(this->raw, &wrappedValue, sizeof({{ cType }}));
46+
{% endif %}
4147
{% endif %}
4248

4349
this->ConstructFields();
@@ -83,7 +89,6 @@ void {{ cppClassName }}::ConstructFields() {
8389
// Set the static method call and set the payload for this function to be
8490
// the current instance
8591
this->raw->{{ field.name }} = NULL;
86-
//TODO: solve this problem
8792
{% if isExtendedStruct %}
8893
(({{ cType }}_extended *)this->raw)->payload = (void *)this;
8994
{% else %}

lib/filter_registry.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
var NodeGit = require("../");
2+
var normalizeOptions = NodeGit.Utils.normalizeOptions;
3+
4+
var FilterRegistry = NodeGit.FilterRegistry;
5+
6+
var _register = FilterRegistry.register;
7+
8+
// Override FilterRegistry.register to normalize Filter
9+
FilterRegistry.register = function(name, filter, priority) {
10+
filter = normalizeOptions(filter, NodeGit.Filter);
11+
console.log("[DEBUG] Filter: ", filter);
12+
if(filter.check && filter.apply) {
13+
return _register(name, filter, priority);
14+
}
15+
else {
16+
console.log(
17+
"ERROR: please provide check and (apply or stream) callbacks for filter");
18+
return null;
19+
}
20+
};

test/tests/filter.js

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
var assert = require("assert"),
2+
promisify = require("promisify-node"),
3+
fse = promisify(require("fs-extra")),
4+
path = require("path"),
5+
local = path.join.bind(path, __dirname);
6+
7+
describe.only("Filter", function() {
8+
var NodeGit = require("../../");
9+
10+
var emptyRepoPath = local("../repos/empty"),
11+
filterName = "psuedo_filter",
12+
// newRepoPath = local("../repos/newrepo"),
13+
Registry = NodeGit.FilterRegistry,
14+
Checkout = NodeGit.Checkout,
15+
Repository = NodeGit.Repository,
16+
Attr = NodeGit.Attr,
17+
Status = NodeGit.Status,
18+
reposPath = local("../repos/workdir");
19+
20+
beforeEach(function() {
21+
var test = this;
22+
23+
return Repository.open(reposPath)
24+
.then(function(repository) {
25+
test.repository = repository;
26+
})
27+
.then(function() {
28+
return Repository.open(emptyRepoPath);
29+
})
30+
.then(function(emptyRepo) {
31+
test.emptyRepo = emptyRepo;
32+
});
33+
});
34+
35+
afterEach(function() {
36+
//Unregistering the filter to avoid GIT_EEXISTS
37+
Registry.unregister(filterName);
38+
});
39+
40+
it("Registering filter for the first time", function() {
41+
// registering custom filter
42+
var result = Registry.register(filterName, {
43+
initialize: function() {
44+
console.log("inside INIT");
45+
},
46+
apply: function() {
47+
console.log("inside APPLY");
48+
},
49+
stream: function() {
50+
console.log("inside STREAM");
51+
},
52+
check: function(){
53+
console.log("inside CHECK");
54+
}
55+
}, 0);
56+
assert.strictEqual(result, 0);
57+
});
58+
59+
it("Registering filter and re-registering same filter", function() {
60+
// registering custom filter
61+
var result = Registry.register(filterName, {
62+
initialize: function() {
63+
console.log("inside INIT");
64+
},
65+
apply: function() {
66+
console.log("inside APPLY");
67+
},
68+
stream: function() {
69+
console.log("inside STREAM");
70+
},
71+
check: function(){
72+
console.log("inside CHECK");
73+
}
74+
}, 0);
75+
assert.strictEqual(result, 0);
76+
77+
result = Registry.register(filterName, {
78+
initialize: function() {
79+
console.log("inside INIT");
80+
},
81+
apply: function() {
82+
console.log("inside APPLY");
83+
},
84+
stream: function() {
85+
console.log("inside STREAM");
86+
},
87+
check: function(){
88+
console.log("inside CHECK");
89+
}
90+
}, 0);
91+
assert.strictEqual(result, -4);
92+
});
93+
94+
it("Testing Initialize callback", function() {
95+
var test = this,
96+
testFilePath = path.join(reposPath, "package.json"),
97+
flags = Status.SHOW.INDEX_AND_WORKDIR;
98+
99+
// registering custom filter
100+
var result = Registry.register(filterName, {
101+
initialize: function() {
102+
console.log("inside INIT");
103+
},
104+
apply: function() {
105+
console.log("inside APPLY");
106+
},
107+
stream: function() {
108+
console.log("inside STREAM");
109+
},
110+
check: function(){
111+
console.log("inside CHECK");
112+
}
113+
}, 0);
114+
115+
assert.strictEqual(result, 0);
116+
117+
// creating .gitattributes
118+
var gitattributeFilePromise = fse.writeFile(
119+
path.join(reposPath, ".gitattributes"),
120+
"* filter="+ filterName +" diff=lfs merge=lfs -text", {
121+
encoding: "utf-8",
122+
});
123+
//creating test file that will be used to trigger custom filter
124+
var testFilePromise = fse.writeFile(
125+
testFilePath,
126+
"initial text", {
127+
encoding: "utf-8",
128+
});
129+
130+
Attr.cacheFlush(this.repository);
131+
132+
// setup complete, testing initialize of custom filter
133+
return Promise.all([gitattributeFilePromise, testFilePromise])
134+
// create necessary files
135+
.then(function() {
136+
return Attr.get(
137+
test.repository,
138+
flags,
139+
path.join(reposPath, ".gitattributes"),
140+
"filter");
141+
})
142+
// check attribute values
143+
.then(function(data) {
144+
console.log("data: ", data);
145+
assert.strictEqual(data, filterName);
146+
})
147+
// modify file
148+
.then(function() {
149+
return fse.writeFile(testFilePath,
150+
"Modified Content",
151+
{
152+
encoding: "utf-8"
153+
});
154+
})
155+
// perform checkout, which should trigger filter
156+
.then(function() {
157+
var opts = {
158+
checkoutStrategy: Checkout.STRATEGY.FORCE,
159+
paths: "package.json"
160+
};
161+
return Checkout.head(test.repository, opts);
162+
})
163+
.then(function() {
164+
console.log("Post checkout");
165+
});
166+
});
167+
168+
});

0 commit comments

Comments
 (0)