1# ====================================================================
2#    Licensed to the Apache Software Foundation (ASF) under one
3#    or more contributor license agreements.  See the NOTICE file
4#    distributed with this work for additional information
5#    regarding copyright ownership.  The ASF licenses this file
6#    to you under the Apache License, Version 2.0 (the
7#    "License"); you may not use this file except in compliance
8#    with the License.  You may obtain a copy of the License at
9#
10#      http://www.apache.org/licenses/LICENSE-2.0
11#
12#    Unless required by applicable law or agreed to in writing,
13#    software distributed under the License is distributed on an
14#    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15#    KIND, either express or implied.  See the License for the
16#    specific language governing permissions and limitations
17#    under the License.
18# ====================================================================
19
20require 'etc'
21require 'fileutils'
22
23module SvnTestUtil
24  module Windows
25    module Svnserve
26      def service_name
27        "test-svn-server--port-#{@svnserve_port}"
28      end
29
30      class << self
31        def escape_value(value)
32          escaped_value = value.gsub(/"/, '\\"') # "
33          "\"#{escaped_value}\""
34        end
35      end
36
37      def setup_svnserve
38        @svnserve_port = @svnserve_ports.last
39        @repos_svnserve_uri = "svn://#{@svnserve_host}:#{@svnserve_port}"
40
41        @@service_created ||= begin
42          @@service_created = true
43
44          top_directory = File.join(File.dirname(__FILE__), "..", "..", "..", "..", "..")
45          build_type = ENV["BUILD_TYPE"] || "Release"
46          svnserve_path = File.join(top_directory, build_type, 'subversion', 'svnserve', 'svnserve.exe')
47          svnserve_path = Svnserve.escape_value(svnserve_path)
48
49          root = @full_repos_path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
50          FileUtils.mkdir_p(root)
51
52          IO.popen("#{svnserve_path} -d -r #{Svnserve.escape_value(root)} --listen-host #{@svnserve_host} --listen-port #{@svnserve_port} --pid-file #{@svnserve_pid_file}")
53          user = ENV["USERNAME"] || Etc.getlogin
54
55          # Give svnserve a bit of time to start
56          sleep 1
57        end
58        true
59      end
60
61      def teardown_svnserve
62        # TODO:
63        #   Load @svnserve_pid_file
64        #   Kill process
65      end
66
67      def add_pre_revprop_change_hook
68        File.open("#{@repos.pre_revprop_change_hook}.cmd", "w") do |hook|
69          hook.print <<-HOOK
70set REPOS=%1
71set REV=%2
72set USER=%3
73set PROPNAME=%4
74if "%PROPNAME%" == "#{Svn::Core::PROP_REVISION_LOG}" if "%USER%" == "#{@author}" exit 0
75exit 1
76          HOOK
77        end
78      end
79    end
80
81    module SetupEnvironment
82      def setup_test_environment(top_dir, base_dir, ext_dir)
83        @@top_dir = top_dir
84
85        build_type = ENV["BUILD_TYPE"] || "Release"
86
87        FileUtils.mkdir_p(ext_dir)
88
89        relative_base_dir =
90          base_dir.sub(/^#{Regexp.escape(top_dir + File::SEPARATOR)}/, '')
91        build_base_dir = File.join(top_dir, build_type, relative_base_dir)
92
93        dll_dir = File.expand_path(build_base_dir)
94        subversion_dir = File.join(build_base_dir, "..", "..", "..")
95        subversion_dir = File.expand_path(subversion_dir)
96
97        util_name = "util"
98        build_conf = File.join(top_dir, "build.conf")
99        File.open(File.join(ext_dir, "#{util_name}.rb" ), 'w') do |util|
100          setup_dll_wrapper_util(dll_dir, util)
101          add_depended_dll_path_to_dll_wrapper_util(top_dir, build_type, util)
102          add_svn_dll_path_to_dll_wrapper_util(build_conf, subversion_dir, util)
103          setup_dll_wrappers(build_conf, ext_dir, dll_dir, util_name) do |lib|
104            svn_lib_dir = File.join(subversion_dir, "libsvn_#{lib}")
105            util.puts("add_path.call(#{svn_lib_dir.dump})")
106          end
107
108          svnserve_dir = File.join(subversion_dir, "svnserve")
109          util.puts("add_path.call(#{svnserve_dir.dump})")
110        end
111      end
112
113      def gen_make_opts
114        @gen_make_opts ||= begin
115          lines = []
116          gen_make_opts = File.join(@@top_dir, "gen-make.opts")
117          lines =
118            File.read(gen_make_opts).lines.to_a if File.exists?(gen_make_opts)
119          config = Hash.new do |hash, key|
120            if /^--with-(.*)$/ =~ key
121              hash[key] = File.join(@@top_dir, $1)
122            end
123          end
124
125          lines.each do |line|
126            name, value = line.chomp.split(/\s*=\s*/, 2)
127            if value
128              config[name] = Pathname.new(value).absolute? ?
129                value :
130                File.join(@@top_dir, value)
131            end
132          end
133          config
134        end
135      end
136      module_function :gen_make_opts
137
138      private
139      def setup_dll_wrapper_util(dll_dir, util)
140        libsvn_swig_ruby_dll_dir = File.join(dll_dir, "libsvn_swig_ruby")
141
142        util.puts(<<-EOC)
143paths = ENV["PATH"].split(';')
144add_path = Proc.new do |path|
145  win_path = path.tr(File::SEPARATOR, File::ALT_SEPARATOR)
146  unless paths.include?(win_path)
147    ENV["PATH"] = "\#{win_path};\#{ENV['PATH']}"
148  end
149end
150
151add_path.call(#{dll_dir.dump})
152add_path.call(#{libsvn_swig_ruby_dll_dir.dump})
153EOC
154      end
155
156      def add_depended_dll_path_to_dll_wrapper_util(top_dir, build_type, util)
157        [
158         ["apr", build_type],
159         ["apr-util", build_type],
160         ["apr-iconv", build_type],
161         ["berkeley-db", "bin"],
162         ["libintl", "bin"],
163         ["sasl", "lib"],
164        ].each do |lib, sub_dir|
165          lib_dir = Pathname.new(gen_make_opts["--with-#{lib}"])
166          dll_dir = lib_dir + sub_dir
167          dll_dir = dll_dir.expand_path
168          util.puts("add_path.call(#{dll_dir.to_s.dump})")
169        end
170      end
171
172      def add_svn_dll_path_to_dll_wrapper_util(build_conf, subversion_dir, util)
173        File.open(build_conf) do |f|
174          f.each do |line|
175            if /^\[(libsvn_.+)\]\s*$/ =~ line
176              lib_name = $1
177              lib_dir = File.join(subversion_dir, lib_name)
178              util.puts("add_path.call(#{lib_dir.dump})")
179            end
180          end
181        end
182      end
183
184      def setup_dll_wrappers(build_conf, ext_dir, dll_dir, util_name)
185        File.open(build_conf) do |f|
186          f.each do |line|
187            if /^\[swig_(.+)\]\s*$/ =~ line
188              lib_name = $1
189              File.open(File.join(ext_dir, "#{lib_name}.rb" ), 'w') do |rb|
190                rb.puts(<<-EOC)
191require File.join(File.dirname(__FILE__), #{util_name.dump})
192require File.join(#{dll_dir.dump}, File.basename(__FILE__, '.rb')) + '.so'
193EOC
194              end
195
196              yield(lib_name)
197            end
198          end
199        end
200      end
201    end
202  end
203end
204