123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155 |
- /**
- * 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) {
- var logic = './logic/' + name + '.js'
- try { require(logic)(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!
- })
- }
- }
|