summaryrefslogtreecommitdiff
path: root/node_modules/dir-compare/src/entry/entryEquality.js
blob: f1b8d781d6b872e89e2a376aed453e355ea22133 (about) (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
var fs = require('fs')
/**
 * Compares two entries with identical name and type.
 */
module.exports = {
    isEntryEqualSync: function (entry1, entry2, type, options) {
        if (type === 'file') {
            return isFileEqualSync(entry1, entry2, options)
        }
        if (type === 'directory') {
            return isDirectoryEqual(entry1, entry2, options)
        }
        if (type === 'broken-link') {
            return isBrokenLinkEqual()
        }
        throw new Error('Unexpected type ' + type)
    },

    isEntryEqualAsync: function (entry1, entry2, type, diffSet, options) {
        if (type === 'file') {
            return isFileEqualAsync(entry1, entry2, type, diffSet, options)
        }
        if (type === 'directory') {
            return isDirectoryEqual(entry1, entry2, options)
        }
        if (type === 'broken-link') {
            return isBrokenLinkEqual()
        }
        throw new Error('Unexpected type ' + type)
    }
}


function isFileEqualSync(entry1, entry2, options) {
    var p1 = entry1 ? entry1.absolutePath : undefined
    var p2 = entry2 ? entry2.absolutePath : undefined
    if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
        return { same: false, reason: 'different-symlink' }
    }
    if (options.compareSize && entry1.stat.size !== entry2.stat.size) {
        return { same: false, reason: 'different-size' }
    }
    if (options.compareDate && !isDateEqual(entry1.stat.mtime, entry2.stat.mtime, options.dateTolerance)) {
        return { same: false, reason: 'different-date' }
    }
    if (options.compareContent && !options.compareFileSync(p1, entry1.stat, p2, entry2.stat, options)) {
        return { same: false, reason: 'different-content' }
    }
    return { same: true }
}

function isFileEqualAsync(entry1, entry2, type, diffSet, options) {
    var p1 = entry1 ? entry1.absolutePath : undefined
    var p2 = entry2 ? entry2.absolutePath : undefined
    if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
        return { same: false, reason: 'different-symlink' }
    }
    if (options.compareSize && entry1.stat.size !== entry2.stat.size) {
        return { same: false, samePromise: undefined, reason: 'different-size' }
    }

    if (options.compareDate && !isDateEqual(entry1.stat.mtime, entry2.stat.mtime, options.dateTolerance)) {
        return { same: false, samePromise: undefined, reason: 'different-date' }
    }

    if (options.compareContent) {
        var samePromise = undefined
        var subDiffSet
        if (!options.noDiffSet) {
            subDiffSet = []
            diffSet.push(subDiffSet)
        }
        samePromise = options.compareFileAsync(p1, entry1.stat, p2, entry2.stat, options)
            .then(function (comparisonResult) {
                var same, error
                if (typeof (comparisonResult) === "boolean") {
                    same = comparisonResult
                } else {
                    error = comparisonResult
                }

                return {
                    entry1: entry1, entry2: entry2, same: same,
                    error: error, type1: type, type2: type,
                    diffSet: subDiffSet,
                    reason: same ? undefined : 'different-content'
                }
            })
            .catch(function (error) {
                return {
                    error: error
                }
            })

        return { same: undefined, samePromise: samePromise }
    }

    return { same: true, samePromise: undefined }
}

function isDirectoryEqual(entry1, entry2, options) {
    if (options.compareSymlink && !isSymlinkEqual(entry1, entry2)) {
        return { same: false, reason: 'different-symlink' }
    }
    return { same: true }
}

function isBrokenLinkEqual() {
    return { same: false, reason: 'broken-link' } // broken links are never considered equal
}

/**
 * Compares two dates and returns true/false depending on tolerance (milliseconds).
 * Two dates are considered equal if the difference in milliseconds between them is less or equal than tolerance.
 */
function isDateEqual(date1, date2, tolerance) {
    return Math.abs(date1.getTime() - date2.getTime()) <= tolerance ? true : false
}

/**
 * Compares two entries for symlink equality.
 */
function isSymlinkEqual(entry1, entry2) {
    if (!entry1.isSymlink && !entry2.isSymlink) {
        return true
    }
    if (entry1.isSymlink && entry2.isSymlink && hasIdenticalLink(entry1.absolutePath, entry2.absolutePath)) {
        return true
    }
    return false
}

function hasIdenticalLink(path1, path2) {
    return fs.readlinkSync(path1) === fs.readlinkSync(path2)
}