diff options
Diffstat (limited to 'lib/tasks/themes.rake')
| -rw-r--r-- | lib/tasks/themes.rake | 142 | 
1 files changed, 86 insertions, 56 deletions
diff --git a/lib/tasks/themes.rake b/lib/tasks/themes.rake index 1eed92f1e..4a864d141 100644 --- a/lib/tasks/themes.rake +++ b/lib/tasks/themes.rake @@ -1,94 +1,123 @@ +require Rails.root.join('commonlib', 'rblib', 'git') +  namespace :themes do -    def plugin_dir -        File.join(Rails.root,"vendor","plugins") +    # Alias the module so we don't need the MySociety prefix here +    Git = MySociety::Git + +    def all_themes_dir +        File.join(Rails.root,"lib","themes")      end      def theme_dir(theme_name) -        File.join(plugin_dir, theme_name) +        File.join(all_themes_dir, theme_name)      end -    def checkout(commitish) -        puts "Checking out #{commitish}" if verbose -        system "git checkout #{commitish}" +    def old_all_themes_dir(theme_name) +        File.join(Rails.root, "vendor", "plugins", theme_name)      end -    def checkout_tag(version) -        checkout usage_tag(version) +    def possible_theme_dirs(theme_name) +        [theme_dir(theme_name), old_all_themes_dir(theme_name)]      end -    def checkout_remote_branch(branch) -        checkout "origin/#{branch}" +    def installed?(theme_name) +        possible_theme_dirs(theme_name).any? { |dir| File.directory? dir }      end      def usage_tag(version)          "use-with-alaveteli-#{version}"      end -    def install_theme_using_git(name, uri, verbose=false, options={}) -        install_path = theme_dir(name) -        Dir.chdir(plugin_dir) do -            clone_command = "git clone #{uri} #{name}" -            if system(clone_command) -                Dir.chdir install_path do -                    # First try to checkout a specific branch of the theme -                    tag_checked_out = checkout_remote_branch(AlaveteliConfiguration::theme_branch) if AlaveteliConfiguration::theme_branch -                    if !tag_checked_out -                        # try to checkout a tag exactly matching ALAVETELI VERSION -                        tag_checked_out = checkout_tag(ALAVETELI_VERSION) -                    end -                    if ! tag_checked_out -                        # if we're on a hotfix release (four sequence elements or more), -                        # look for a usage tag matching the minor release (three sequence elements) -                        # and check that out if found -                        if hotfix_version = /^(\d+\.\d+\.\d+)(\.\d+)+/.match(ALAVETELI_VERSION) -                            base_version = hotfix_version[1] -                            tag_checked_out = checkout_tag(base_version) -                        end -                    end -                    if ! tag_checked_out -                        puts "No specific tag for this version: using HEAD" if verbose -                    end -                    puts "removing: .git .gitignore" if verbose -                    rm_rf %w(.git .gitignore) -                end -            else -                rm_rf install_path -                raise "#{clone_command} failed! Stopping." -            end -        end -    end -      def uninstall(theme_name, verbose=false) -        dir = theme_dir(theme_name) -        if File.directory?(dir) -            run_hook(theme_name, 'uninstall', verbose) -            puts "Removing '#{dir}'" if verbose -            rm_r dir -        else -            puts "Plugin doesn't exist: #{dir}" +        possible_theme_dirs(theme_name).each do |dir| +            if File.directory?(dir) +                run_hook(theme_name, 'uninstall', verbose) +            end          end      end      def run_hook(theme_name, hook_name, verbose=false) -        hook_file = File.join(theme_dir(theme_name), "#{hook_name}.rb") +        directory = theme_dir(theme_name) +        hook_file = File.join(directory, "#{hook_name}.rb")          if File.exist? hook_file -            puts "Running #{hook_name} hook for #{theme_name}" if verbose +            puts "Running #{hook_name} hook in #{directory}" if verbose              load hook_file          end      end -    def installed?(theme_name) -        File.directory?(theme_dir(theme_name)) +    def move_old_theme(old_theme_directory) +        puts "There was an old-style theme at #{old_theme_directory}" if verbose +        moved_directory = "#{old_theme_directory}-moved" +        begin +            File.rename old_theme_directory, moved_directory +        rescue Errno::ENOTEMPTY, Errno::EEXIST +            raise "Tried to move #{old_theme_directory} out of the way, " \ +                "but #{moved_directory} already existed" +        end +    end + +    def committishes_to_try +        result = [] +        theme_branch = AlaveteliConfiguration::theme_branch +        result.push "origin/#{theme_branch}" if theme_branch +        result.push usage_tag(ALAVETELI_VERSION) +        hotfix_match = /^(\d+\.\d+\.\d+)(\.\d+)+/.match(ALAVETELI_VERSION) +        result.push usage_tag(hotfix_match[1]) if hotfix_match +        result +    end + +    def checkout_best_option(theme_name) +        theme_directory = theme_dir theme_name +        all_failed = true +        committishes_to_try.each do |committish| +            if Git.committish_exists? theme_directory, committish +                puts "Checking out #{committish}" if verbose +                Git.checkout theme_directory, committish +                all_failed = false +                break +            else +                puts "Failed to find #{committish}; skipping..." if verbose +            end +        end +        puts "Falling to using HEAD instead" if all_failed and verbose      end      def install_theme(theme_url, verbose, deprecated=false) +        FileUtils.mkdir_p all_themes_dir          deprecation_string = deprecated ? " using deprecated THEME_URL" : ""          theme_name = theme_url_to_theme_name theme_url          puts "Installing theme #{theme_name}#{deprecation_string} from #{theme_url}" +        # Make sure any uninstall hooks have been run:          uninstall(theme_name, verbose) if installed?(theme_name) -        install_theme_using_git(theme_name, theme_url, verbose) +        theme_directory = theme_dir theme_name +        # Is there an old-style theme directory there?  If so, move it +        # out of the way so that there's no risk that work is lost: +        if File.directory? theme_directory +            unless Git.non_bare_repository? theme_directory +                move_old_theme theme_directory +            end +        end +        # If there isn't a directory there already, clone it into place: +        unless File.directory? theme_directory +            unless system "git", "clone", theme_url, theme_directory +                raise "Cloning from #{theme_url} to #{theme_directory} failed" +            end +        end +        # Set the URL for origin in case it has changed, and fetch from there: +        Git.remote_set_url theme_directory, 'origin', theme_url +        Git.fetch theme_directory, 'origin' +        # Check that checking-out a new commit will be safe: +        unless Git.status_clean theme_directory +            raise "There were uncommitted changes in #{theme_directory}" +        end +        unless Git.is_HEAD_pushed? theme_directory +            raise "The current work in #{theme_directory} is unpushed" +        end +        # Now try to checkout various commits in order of preference: +        checkout_best_option theme_name +        # Finally run the install hooks:          run_hook(theme_name, 'install', verbose)          run_hook(theme_name, 'post_install', verbose)      end @@ -102,4 +131,5 @@ namespace :themes do              install_theme(AlaveteliConfiguration::theme_url, verbose, deprecated=true)          end      end +  end  | 
