function signApplicationAsync (opts) {
  return walkAsync(getAppContentsPath(opts))
    .then(function (childPaths) {
      function ignoreFilePath (opts, filePath) {
        if (opts.ignore) {
          return opts.ignore.some(function (ignore) {
            if (typeof ignore === 'function') {
              return ignore(filePath)
            }
            return filePath.match(ignore)
          })
        }
        return false
      }

      if (opts.binaries) childPaths = childPaths.concat(opts.binaries)

      var args = [
        '--sign', opts.identity.hash || opts.identity.name,
        '--force'
      ]
      if (opts.keychain) {
        args.push('--keychain', opts.keychain)
      }
      if (opts.requirements) {
        args.push('--requirements', opts.requirements)
      }
      if (opts.timestamp) {
        args.push('--timestamp', opts.timestamp)
      }

      var promise
      if (opts.entitlements) {
        // Sign with entitlements
        promise = Promise.mapSeries(childPaths, function (filePath) {
          if (ignoreFilePath(opts, filePath)) {
            debuglog('Skipped... ' + filePath)
            return
          }
          debuglog('Signing... ' + filePath)
          return execFileAsync('codesign', args.concat('--entitlements', opts['entitlements-inherit'], filePath))
        })
          .then(function () {
            debuglog('Signing... ' + opts.app)
            return execFileAsync('codesign', args.concat('--entitlements', opts.entitlements, opts.app))
          })
      } else {
        // Otherwise normally
        promise = Promise.mapSeries(childPaths, function (filePath) {
          if (ignoreFilePath(opts, filePath)) {
            debuglog('Skipped... ' + filePath)
            return
          }
          debuglog('Signing... ' + filePath)
          return execFileAsync('codesign', args.concat(filePath))
        })
          .then(function () {
            debuglog('Signing... ' + opts.app)
            return execFileAsync('codesign', args.concat(opts.app))
          })
      }

      return promise
        .then(function () {
          // Verify code sign
          debuglog('Verifying...')
          var promise = verifySignApplicationAsync(opts)
            .then(function (result) {
              debuglog('Verified.')
            })

          // Check entitlements if applicable
          if (opts.entitlements) {
            promise = promise
              .then(function () {
                debuglog('Displaying entitlements...')
                return execFileAsync('codesign', [
                  '--display',
                  '--entitlements', ':-', // Write to standard output and strip off the blob header
                  opts.app
                ])
              })
              .then(function (result) {
                debuglog('Entitlements:', '\n',
                  result)
              })
          }

          return promise
        })
    })
}
This function returns a promise codesigning only.
@function
@param {Object} opts - Options.
@returns {Promise} Promise.