Skip to content

Commit cd80fcc

Browse files
author
Andrei
committed
Merge pull request nodeSolidServer#215 from linkeddata/fix-delete
Fix delete on containers
2 parents ed7f186 + 711b03a commit cd80fcc

File tree

3 files changed

+112
-24
lines changed

3 files changed

+112
-24
lines changed

lib/ldp.js

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ var error = require('./http-error')
1515
var stringToStream = require('./utils').stringToStream
1616
var extend = require('extend')
1717
var doWhilst = require('async').doWhilst
18+
var rimraf = require('rimraf')
1819
var turtleExtension = '.ttl'
1920

2021
function LDP (argv) {
@@ -424,24 +425,39 @@ LDP.prototype.delete = function (host, resourcePath, callback) {
424425
}
425426

426427
if (stats.isDirectory()) {
427-
return ldp.deleteContainerMetadata(filename, callback)
428+
return ldp.deleteContainer(filename, callback)
428429
} else {
429430
return ldp.deleteResource(filename, callback)
430431
}
431432
})
432433
}
433434

434-
LDP.prototype.deleteContainerMetadata = function (directory, callback) {
435+
LDP.prototype.deleteContainer = function (directory, callback) {
436+
var self = this
435437
if (directory[directory.length - 1] !== '/') {
436438
directory += '/'
437439
}
438440

439-
return fs.unlink(directory + this.suffixMeta, function (err, data) {
440-
if (err) {
441-
debug.container('DELETE -- unlink() error: ' + err)
442-
return callback(error(err, 'Failed to delete container'))
441+
var countValid = 0
442+
fs.readdir(directory, function (err, list) {
443+
if (err) return callback(error(404, 'The container does not exist'))
444+
445+
if (list.indexOf(self.suffixMeta) > -1) {
446+
countValid++
443447
}
444-
return callback(null, data)
448+
449+
if (list.indexOf(self.suffixAcl) > -1) {
450+
countValid++
451+
}
452+
453+
if (list.length !== countValid) {
454+
return callback(error(409, 'Container is not empty'))
455+
}
456+
457+
return rimraf(directory, function (err) {
458+
if (err) return callback(error(err, 'Failed to delete the container'))
459+
return callback(null)
460+
})
445461
})
446462
}
447463

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
"chai": "^3.0.0",
5757
"mocha": "^2.2.5",
5858
"nock": "^2.10.0",
59+
"rsvp": "^3.1.0",
5960
"standard": "^5.4.1",
6061
"supertest": "^1.0.1"
6162
},

test/http.js

Lines changed: 88 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,51 @@ var fs = require('fs')
33
var li = require('li')
44
var ldnode = require('../index')
55
var rm = require('./test-utils').rm
6+
var RSVP = require('rsvp')
7+
8+
var suffixAcl = '.acl'
9+
var suffixMeta = '.meta'
10+
var ldpServer = ldnode({
11+
root: __dirname + '/resources'
12+
})
13+
var server = supertest(ldpServer)
14+
15+
/**
16+
* Creates a new test basic container via an LDP POST
17+
* (located in `test/resources/{containerName}`)
18+
* @method createTestContainer
19+
* @param containerName {String} Container name used as slug, no leading `/`
20+
* @return {RSVP.Promise} Promise obj, for use with Mocha's `before()` etc
21+
*/
22+
function createTestContainer (containerName) {
23+
return new RSVP.Promise(function (resolve, reject) {
24+
server.post('/')
25+
.set('content-type', 'text/turtle')
26+
.set('slug', containerName)
27+
.set('link', '<http://www.w3.org/ns/ldp#BasicContainer>; rel="type"')
28+
.set('content-type', 'text/turtle')
29+
.end(function (error, res) {
30+
error ? reject(error) : resolve(res)
31+
})
32+
})
33+
}
34+
35+
/**
36+
* Creates a new turtle test resource via an LDP PUT
37+
* (located in `test/resources/{resourceName}`)
38+
* @method createTestResource
39+
* @param resourceName {String} Resource name (should have a leading `/`)
40+
* @return {RSVP.Promise} Promise obj, for use with Mocha's `before()` etc
41+
*/
42+
function createTestResource (resourceName) {
43+
return new RSVP.Promise(function (resolve, reject) {
44+
server.put(resourceName)
45+
.set('content-type', 'text/turtle')
46+
.end(function (error, res) {
47+
error ? reject(error) : resolve(res)
48+
})
49+
})
50+
}
651

752
describe('HTTP APIs', function () {
853
var emptyResponse = function (res) {
@@ -35,15 +80,6 @@ describe('HTTP APIs', function () {
3580
return handler
3681
}
3782

38-
var ldpServer = ldnode({
39-
root: __dirname + '/resources'
40-
})
41-
42-
var suffixAcl = '.acl'
43-
var suffixMeta = '.meta'
44-
45-
var server = supertest(ldpServer)
46-
4783
describe('GET Root container', function () {
4884
it('should have Access-Control-Allow-Origin as the req.Origin', function (done) {
4985
server.get('/')
@@ -265,29 +301,64 @@ describe('HTTP APIs', function () {
265301
.set('content-type', 'text/turtle')
266302
.expect(hasHeader('describedBy', 'baz.ttl' + suffixMeta))
267303
.expect(hasHeader('acl', 'baz.ttl' + suffixAcl))
268-
.expect(function () {
269-
fs.unlinkSync(__dirname + '/resources/foo/bar/baz.ttl')
270-
fs.rmdirSync(__dirname + '/resources/foo/bar/')
271-
fs.rmdirSync(__dirname + '/resources/foo/')
272-
})
273304
.expect(201, done)
274305
})
275-
it('should return 409 code when trying to put to a container', function (done) {
276-
server.put('/')
277-
.expect(409, done)
306+
it('should return 409 code when trying to put to a container',
307+
function (done) {
308+
server.put('/')
309+
.expect(409, done)
310+
}
311+
)
312+
// Cleanup
313+
after(function () {
314+
rm('/foo/')
278315
})
279316
})
280317

281318
describe('DELETE API', function () {
319+
before(function () {
320+
// Ensure all these are finished before running tests
321+
return RSVP.all([
322+
rm('/false-file-48484848'),
323+
createTestContainer('delete-test-empty-container'),
324+
createTestResource('/put-resource-1.ttl'),
325+
createTestContainer('delete-test-non-empty'),
326+
createTestResource('/delete-test-non-empty/test.ttl')
327+
])
328+
})
329+
282330
it('should return 404 status when deleting a file that does not exists',
283331
function (done) {
284332
server.delete('/false-file-48484848')
285333
.expect(404, done)
286334
})
335+
287336
it('should delete previously PUT file', function (done) {
288337
server.delete('/put-resource-1.ttl')
289338
.expect(200, done)
290339
})
340+
341+
it('should fail to delete non-empty containers', function (done) {
342+
server.delete('/delete-test-non-empty/')
343+
.expect(409, done)
344+
})
345+
346+
it('should delete a new and empty container', function (done) {
347+
server.delete('/delete-test-empty-container/')
348+
.expect(function () {
349+
// Ensure container was deleted
350+
server.get('/delete-test-empty-container/')
351+
.expect(404)
352+
})
353+
.end(done)
354+
})
355+
356+
after(function () {
357+
// Clean up after DELETE API tests
358+
rm('/put-resource-1.ttl')
359+
rm('/delete-test-non-empty/')
360+
rm('/delete-test-empty-container/')
361+
})
291362
})
292363

293364
describe('POST API', function () {

0 commit comments

Comments
 (0)