File size: 4,781 Bytes
bc20498 |
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
/**
* Things we will need
*/
var async = require('async')
var distros = require('./os.json')
var fs = require('fs')
var os = require('os')
/**
* Begin definition of globals.
*/
var cachedDistro = null // Store result of getLinuxDistro() after first call
/**
* Module definition.
*/
module.exports = function getOs (cb) {
// Node builtin as first line of defense.
var osName = os.platform()
// Linux is a special case.
if (osName === 'linux') return getLinuxDistro(cb)
// Else, node's builtin is acceptable.
return cb(null, { os: osName })
}
/**
* Identify the actual distribution name on a linux box.
*/
function getLinuxDistro (cb) {
/**
* First, we check to see if this function has been called before.
* Since an OS doesn't change during runtime, its safe to cache
* the result and return it for future calls.
*/
if (cachedDistro) return cb(null, cachedDistro)
/**
* We are going to take our list of release files from os.json and
* check to see which one exists. It is safe to assume that no more
* than 1 file in the list from os.json will exist on a distribution.
*/
getReleaseFile(Object.keys(distros), function (e, file) {
if (e) return cb(e)
/**
* Multiple distributions may share the same release file.
* We get our array of candidates and match the format of the release
* files and match them to a potential distribution
*/
var candidates = distros[file]
var os = { os: 'linux', dist: candidates[0] }
fs.readFile(file, 'utf-8', function (e, file) {
if (e) return cb(e)
/**
* If we only know of one distribution that has this file, its
* somewhat safe to assume that it is the distribution we are
* running on.
*/
if (candidates.length === 1) {
return customLogic(os, getName(os.dist), file, function (e, os) {
if (e) return cb(e)
cachedDistro = os
return cb(null, os)
})
}
/**
* First, set everything to lower case to keep inconsistent
* specifications from mucking up our logic.
*/
file = file.toLowerCase()
/**
* Now we need to check all of our potential candidates one by one.
* If their name is in the release file, it is guarenteed to be the
* distribution we are running on. If distributions share the same
* release file, it is reasonably safe to assume they will have the
* distribution name stored in their release file.
*/
async.each(candidates, function (candidate, done) {
var name = getName(candidate)
if (file.indexOf(name) >= 0) {
os.dist = candidate
return customLogic(os, name, file, function (e, augmentedOs) {
if (e) return done(e)
os = augmentedOs
return done()
})
} else {
return done()
}
}, function (e) {
if (e) return cb(e)
cachedDistro = os
return cb(null, os)
})
})
})() // sneaky sneaky.
}
function getName (candidate) {
/**
* We only care about the first word. I.E. for Arch Linux it is safe
* to simply search for "arch". Also note, we force lower case to
* match file.toLowerCase() above.
*/
var index = 0
var name = 'linux'
/**
* Don't include 'linux' when searching since it is too aggressive when
* matching (see #54)
*/
while (name === 'linux') {
name = candidate.split(' ')[index++].toLowerCase()
}
return name
}
/**
* Loads a custom logic module to populate additional distribution information
*/
function customLogic (os, name, file, cb) {
try { require(`./logic/${name}.js`)(os, file, cb) } catch (e) { cb(null, os) }
}
/**
* getReleaseFile() checks an array of filenames and returns the first one it
* finds on the filesystem.
*/
function getReleaseFile (names, cb) {
var index = 0 // Lets keep track of which file we are on.
/**
* checkExists() is a first class function that we are using for recursion.
*/
return function checkExists () {
/**
* Lets get the file metadata off the current file.
*/
fs.stat(names[index], function (e, stat) {
/**
* Now we check if either the file didn't exist, or it is something
* other than a file for some very very bizzar reason.
*/
if (e || !stat.isFile()) {
index++ // If it is not a file, we will check the next one!
if (names.length <= index) { // Unless we are out of files.
return cb(new Error('No unique release file found!')) // Then error.
}
return checkExists() // Re-call this function to check the next file.
}
cb(null, names[index]) // If we found a file, return it!
})
}
}
|