| 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
 | module OS
  module Mac
    X11 = XQuartz = Module.new
    module XQuartz
      extend self
      FORGE_BUNDLE_ID = "org.macosforge.xquartz.X11"
      APPLE_BUNDLE_ID = "org.x.X11"
      FORGE_PKG_ID = "org.macosforge.xquartz.pkg"
      PKGINFO_VERSION_MAP = {
        "2.6.34" => "2.6.3",
        "2.7.4"  => "2.7.0",
        "2.7.14" => "2.7.1",
        "2.7.28" => "2.7.2",
        "2.7.32" => "2.7.3",
        "2.7.43" => "2.7.4",
        "2.7.50" => "2.7.5_rc1",
        "2.7.51" => "2.7.5_rc2",
        "2.7.52" => "2.7.5_rc3",
        "2.7.53" => "2.7.5_rc4",
        "2.7.54" => "2.7.5",
        "2.7.61" => "2.7.6",
        "2.7.73" => "2.7.7",
      }.freeze
      # This returns the version number of XQuartz, not of the upstream X.org.
      # The X11.app distributed by Apple is also XQuartz, and therefore covered
      # by this method.
      def version
        @version ||= detect_version
      end
      def detect_version
        if (path = bundle_path) && path.exist? && (version = version_from_mdls(path))
          version
        elsif prefix.to_s == "/usr/X11"
          guess_system_version
        else
          version_from_pkgutil
        end
      end
      # http://xquartz.macosforge.org/trac/wiki
      # http://xquartz.macosforge.org/trac/wiki/Releases
      def latest_version
        case MacOS.version
        when "10.5"
          "2.6.3"
        else
          "2.7.7"
        end
      end
      def bundle_path
        MacOS.app_with_bundle_id(FORGE_BUNDLE_ID, APPLE_BUNDLE_ID)
      end
      def version_from_mdls(path)
        version = Utils.popen_read(
          "/usr/bin/mdls", "-raw", "-nullMarker", "", "-name", "kMDItemVersion", path.to_s
        ).strip
        version unless version.empty?
      end
      # The XQuartz that Apple shipped in OS X through 10.7 does not have a
      # pkg-util entry, so if Spotlight indexing is disabled we must make an
      # educated guess as to what version is installed.
      def guess_system_version
        case MacOS.version
        when '10.5' then '2.1.6'
        when '10.6' then '2.3.6'
        when '10.7' then '2.6.3'
        else 'dunno'
        end
      end
      # Upstream XQuartz *does* have a pkg-info entry, so if we can't get it
      # from mdls, we can try pkgutil. This is very slow.
      def version_from_pkgutil
        str = MacOS.pkgutil_info(FORGE_PKG_ID)[/version: (\d\.\d\.\d+)$/, 1]
        PKGINFO_VERSION_MAP.fetch(str, str)
      end
      def provided_by_apple?
        [FORGE_BUNDLE_ID, APPLE_BUNDLE_ID].find do |id|
          MacOS.app_with_bundle_id(id)
        end == APPLE_BUNDLE_ID
      end
      # This should really be private, but for compatibility reasons it must
      # remain public. New code should use MacOS::X11.{bin,lib,include}
      # instead, as that accounts for Xcode-only systems.
      def prefix
        @prefix ||= if Pathname.new('/opt/X11/lib/libpng.dylib').exist?
          Pathname.new('/opt/X11')
        elsif Pathname.new('/usr/X11/lib/libpng.dylib').exist?
          Pathname.new('/usr/X11')
        end
      end
      def installed?
        !version.nil? && !prefix.nil?
      end
      # If XQuartz and/or the CLT are installed, headers will be found under
      # /opt/X11/include or /usr/X11/include. For Xcode-only systems, they are
      # found in the SDK, so we use sdk_path for both the headers and libraries.
      # Confusingly, executables (e.g. config scripts) are only found under
      # /opt/X11/bin or /usr/X11/bin in all cases.
      def effective_prefix
        if provided_by_apple? && Xcode.without_clt?
          Pathname.new("#{OS::Mac.sdk_path}/usr/X11")
        else
          prefix
        end
      end
      def bin
        prefix/"bin"
      end
      def include
        effective_prefix/"include"
      end
      def lib
        effective_prefix/"lib"
      end
      def share
        prefix/"share"
      end
    end
  end
end
 |