qcloudhive 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.idea/.rakeTasks +7 -0
  3. data/.idea/Hive.iml +54 -0
  4. data/.idea/dictionaries/dongzhao.xml +7 -0
  5. data/.idea/misc.xml +4 -0
  6. data/.idea/modules.xml +8 -0
  7. data/.idea/vcs.xml +6 -0
  8. data/.idea/workspace.xml +699 -0
  9. data/CODE_OF_CONDUCT.md +74 -0
  10. data/Documents/Images/93A5AC58-17D5-4D3F-B5A8-E509CF429BD0.png +0 -0
  11. data/Documents/Images/C702C824-11B1-47A8-BB15-9F6F14F2B649.png +0 -0
  12. data/Gem/qcloudhive/.idea/misc.xml +4 -0
  13. data/Gem/qcloudhive/.idea/modules.xml +8 -0
  14. data/Gem/qcloudhive/.idea/qcloudhive.iml +8 -0
  15. data/Gem/qcloudhive/.idea/workspace.xml +383 -0
  16. data/Gemfile +4 -0
  17. data/Gemfile.lock +122 -0
  18. data/LICENSE.txt +21 -0
  19. data/README.md +273 -0
  20. data/Rakefile +5 -0
  21. data/bin/console +14 -0
  22. data/bin/setup +8 -0
  23. data/exe/Hive +302 -0
  24. data/lib/qcloudhive.rb +16 -0
  25. data/lib/qcloudhive/config.rb +176 -0
  26. data/lib/qcloudhive/feature.rb +92 -0
  27. data/lib/qcloudhive/framework.rb +192 -0
  28. data/lib/qcloudhive/git_helper.rb +75 -0
  29. data/lib/qcloudhive/gitlab.rb +69 -0
  30. data/lib/qcloudhive/manifest.rb +346 -0
  31. data/lib/qcloudhive/module.rb +228 -0
  32. data/lib/qcloudhive/pod_helper.rb +119 -0
  33. data/lib/qcloudhive/product.rb +32 -0
  34. data/lib/qcloudhive/project.rb +108 -0
  35. data/lib/qcloudhive/repo.rb +177 -0
  36. data/lib/qcloudhive/spec_helper.rb +45 -0
  37. data/lib/qcloudhive/utils.rb +46 -0
  38. data/lib/qcloudhive/version.rb +3 -0
  39. data/lib/qcloudhive/xcodeproj.rb +163 -0
  40. data/qcloudhive.gemspec +43 -0
  41. data/resources/shellscriptes/HiveApp.sh +156 -0
  42. data/resources/shellscriptes/HiveFramework +158 -0
  43. data/resources/shellscriptes/build_framework.sh +76 -0
  44. data/resources/templates/AppDefaultTemplate/.gitignore +41 -0
  45. data/resources/templates/AppDefaultTemplate/AppDefaultTemplate.xcodeproj/project.pbxproj +290 -0
  46. data/resources/templates/AppDefaultTemplate/AppDefaultTemplate.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  47. data/resources/templates/AppDefaultTemplate/AppDefaultTemplate/Info.plist +24 -0
  48. data/resources/templates/AppDefaultTemplate/Podfile +9 -0
  49. data/resources/templates/HiveAppTemplate/.gitignore +41 -0
  50. data/resources/templates/HiveAppTemplate/HiveAppTemplate.xcodeproj/project.pbxproj +539 -0
  51. data/resources/templates/HiveAppTemplate/HiveAppTemplate.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  52. data/resources/templates/HiveAppTemplate/HiveAppTemplate/AppDelegate.h +17 -0
  53. data/resources/templates/HiveAppTemplate/HiveAppTemplate/AppDelegate.m +51 -0
  54. data/resources/templates/HiveAppTemplate/HiveAppTemplate/Assets.xcassets/AppIcon.appiconset/Contents.json +68 -0
  55. data/resources/templates/HiveAppTemplate/HiveAppTemplate/Base.lproj/LaunchScreen.storyboard +27 -0
  56. data/resources/templates/HiveAppTemplate/HiveAppTemplate/Base.lproj/Main.storyboard +26 -0
  57. data/resources/templates/HiveAppTemplate/HiveAppTemplate/Info.plist +45 -0
  58. data/resources/templates/HiveAppTemplate/HiveAppTemplate/ViewController.h +15 -0
  59. data/resources/templates/HiveAppTemplate/HiveAppTemplate/ViewController.m +29 -0
  60. data/resources/templates/HiveAppTemplate/HiveAppTemplate/main.m +16 -0
  61. data/resources/templates/HiveAppTemplate/HiveAppTemplateTests/HiveAppTemplateTests.m +39 -0
  62. data/resources/templates/HiveAppTemplate/HiveAppTemplateTests/Info.plist +22 -0
  63. data/resources/templates/HiveAppTemplate/HiveAppTemplateUITests/HiveAppTemplateUITests.m +40 -0
  64. data/resources/templates/HiveAppTemplate/HiveAppTemplateUITests/Info.plist +22 -0
  65. data/resources/templates/HiveAppTemplate/Podfile +20 -0
  66. data/resources/templates/commonConf.sh +9 -0
  67. data/resources/templates/manifests/build.rb +8 -0
  68. data/resources/templates/manifests/default.xml +12 -0
  69. data/resources/templates/template.podspec +37 -0
  70. metadata +321 -0
@@ -0,0 +1,92 @@
1
+ require_relative "utils.rb"
2
+ require_relative "git_helper.rb"
3
+ require "git"
4
+ require 'versionomy'
5
+
6
+ module QCloudHive
7
+ class QCloudHiveFeature
8
+
9
+ end
10
+
11
+ def QCloudHive.startFeature(cmd, opts)
12
+ end
13
+
14
+ def QCloudHive.listFeature(cmd, opts)
15
+ end
16
+
17
+ def QCloudHive.pushFeature(cmd, opts)
18
+ Config.manifest.projects.each { |p|
19
+ if not p.gitRepo.clean?
20
+ Error("模块:#{p.path} 在本地有未提交的修改,请检查并提交后再进行PUSH操作")
21
+ end
22
+ }
23
+
24
+ Config.manifest.projects.each { |p|
25
+ currentBranch = p.gitRepo.branches[p.gitRepo.current_branch]
26
+ currentFreature = ProjectFeature.new(p, currentBranch)
27
+ if currentFreature.remoteBranch.nil?
28
+ puts "#{p.path} 提交 #{currentBranch.name}"
29
+ L.info("#{p.gitRepo} git repo xxxxxx")
30
+ p.gitRepo.push('origin', currentBranch.name, {"--set-upstream"=>currentBranch.name})
31
+ else
32
+ compareRet = currentFreature.compareRemote
33
+ if compareRet == 1
34
+ puts "#{p.path} 提交 #{currentBranch.name}"
35
+ L.info("#{p.gitRepo} git repo")
36
+ p.gitRepo.push('origin', currentBranch.name, {"--set-upstream"=>currentBranch.name})
37
+ elsif compareRet == -1
38
+ puts "#{p.path} 没有进行push操作 远端有新的修改,请及时Pull⬇️⬇️⬇️".blue
39
+ else
40
+ end
41
+ end
42
+ }
43
+ end
44
+
45
+ def QCloudHive.commitFeature(cmd, opts)
46
+ message = GetOptValue(cmd, opts, :i_message)
47
+ Config.manifest.projects.each { |p|
48
+ if p.exsitLocal?
49
+ git = p.gitRepo
50
+ if (not git.nil?) and (not git.clean?)
51
+ L.info("#{git.dir} commit clean #{git.clean?}")
52
+ git.add(:all=>true)
53
+ git.commit_all(message)
54
+ else
55
+ L.info("#{git.dir} is clean")
56
+ end
57
+ end
58
+ }
59
+ end
60
+
61
+ def QCloudHive.checkDependencies(cmd, opts)
62
+ Config.manifest.projects.each { |p|
63
+ L.info("#{p.path} exist #{p.exsitLocal?}")
64
+ if p.exsitLocal? and (not p.podspec.nil?)
65
+ L.info("#{p.path}")
66
+ version = Versionomy.parse(p.podspec.version.version)
67
+ versionNumber = version.major*1000*1000 + version.minor*1000 + version.tiny
68
+ str = "
69
+ #ifndef #{p.moduleName}ModuleVersion_h
70
+ #define #{p.moduleName}ModuleVersion_h
71
+ #define #{p.moduleName}ModuleVersionNumber #{versionNumber}
72
+ FOUNDATION_EXTERN NSString * const #{p.moduleName}ModuleVersion;
73
+ FOUNDATION_EXTERN NSString * const #{p.moduleName}ModuleName;
74
+ #endif
75
+ "
76
+ file = Pathname(p.localPath).join("Pod/Classes/#{p.moduleName}Version.h")
77
+ File.open(file, "w") { |f|
78
+ f.write str
79
+ }
80
+
81
+ file = Pathname(p.localPath).join("Pod/Classes/#{p.moduleName}Version.m")
82
+ File.open(file, "w") { |f|
83
+ f.write "
84
+ #import \"#{p.moduleName}Version.h\"
85
+ NSString * const #{p.moduleName}ModuleVersion = @\"#{p.podspec.version.version}\";
86
+ NSString * const #{p.moduleName}ModuleName = @\"#{p.moduleName}\";
87
+ "
88
+ }
89
+ end
90
+ }
91
+ end
92
+ end
@@ -0,0 +1,192 @@
1
+
2
+ require_relative "config.rb"
3
+ require "rake"
4
+ require 'fileutils'
5
+ require "set"
6
+ require "pathname"
7
+ class Pathname
8
+ def fileName
9
+ if not extname.nil?
10
+ return basename.to_s[0..(basename.to_s.length-extname.length-1)]
11
+ end
12
+ return basename.to_s
13
+ end
14
+ end
15
+
16
+ module QCloudHive
17
+ class BuildShell
18
+ attr_accessor :productsDir
19
+ attr_accessor :config
20
+ attr_accessor :name
21
+ attr_accessor :other_cflags
22
+ attr_accessor :sdk
23
+ def to_cmd
24
+ cmd ="xcodebuild -configuration #{config} -sdk #{sdk} -workspace #{name}.xcworkspace -scheme #{name} clean\n"
25
+ cmd +="xcodebuild DEPLOYMENT_POSTPROCESSING=YES STRIP_STYLE=debugging "
26
+ if not other_cflags.nil?
27
+ cmd += " OTHER_CFLAGS=#{other_cflags}"
28
+ end
29
+ cmd += " -configuration #{config}"
30
+ cmd += " -workspace #{name}.xcworkspace -scheme #{name}"
31
+ cmd += " -sdk #{sdk} -derivedDataPath #{productsDir} "
32
+ cmd
33
+ end
34
+ end
35
+ def QCloudHive.beginShell(path, shell)
36
+ Rake::sh "cd #{path}\n #{shell}"
37
+ end
38
+
39
+ def QCloudHive.UnlinkedModule(name, hiveXcodeProject)
40
+ podspec = hiveXcodeProject.hiveSpecModules.select { |s|
41
+ s.name == name
42
+ }.first
43
+ if podspec.nil?
44
+ Error "您不想链接的模块#{name}, 不存在本地"
45
+ end
46
+ unlinked = []
47
+ L.info "$$$$$$$$#{podspec.path}"
48
+ if not podspec.path.nil?
49
+ pod = Pod::Specification.from_file(podspec.path)
50
+ vendored_libraries = pod.attributes_hash["vendored_libraries"]
51
+ vendoredFrameworks = pod.attributes_hash["vendored_frameworks"]
52
+ if not vendoredFrameworks.nil?
53
+ vendoredFrameworks.each { |e|
54
+ unlinked << Pathname.new(e).fileName
55
+ }
56
+ end
57
+ if not vendored_libraries.nil?
58
+ vendored_libraries.each { |e|
59
+ name = Pathname.new(e).fileName
60
+ if name.start_with?("lib")
61
+ name = name[3..-1]
62
+ end
63
+ unlinked << name
64
+ }
65
+ end
66
+ L.info "Unlinked #{unlinked}"
67
+ return unlinked
68
+ end
69
+ end
70
+ def QCloudHive.BuildFramework(cmd, opts)
71
+ name = opts[:i_name]
72
+ if name == nil
73
+ L.error "ERROR! no project name, please input one"
74
+ L.error cmd.help
75
+ exit(1)
76
+ end
77
+ buildSimArch = opts[:i_build_sim]
78
+ if buildSimArch.nil?
79
+ buildSimArch = true
80
+ end
81
+ L.info "build sim #{buildSimArch}"
82
+ unlinked = opts[:i_unlinked_frameworks]
83
+ if unlinked.nil?
84
+ unlinked = []
85
+ end
86
+ L.info "un linked frameworks #{unlinked}"
87
+ output = Dir.pwd
88
+ rootShellPath = Config.scriptesDirectory
89
+ Rake::sh "#{rootShellPath}HiveFramework #{name}"
90
+
91
+ projectDir = "#{output}/#{name}"
92
+ project = Xcodeproj::Project.open("#{output}/#{name}/#{name}.xcodeproj")
93
+ project.targets.each do |target|
94
+ if target.name == name
95
+ target.build_configurations.each do |config|
96
+ config.build_settings['ENABLE_BITCODE'] = 'NO'
97
+ puts "set bitcode NO"
98
+ end
99
+ end
100
+ puts "target name #{name}"
101
+ end
102
+
103
+ project.save
104
+
105
+ Rake::sh "cd #{name} \n" +
106
+ "pod update\n"
107
+ # delete unlinked frameworks
108
+ project = Xcodeproj::Project.open("#{output}/#{name}/#{name}.xcodeproj")
109
+ xcconfigFiles = project.files.select{ |f|
110
+ L.info "file #{f.path}"
111
+ f.path.end_with?(".xcconfig")
112
+ }
113
+ L.info("config files #{xcconfigFiles}")
114
+ hiveXcodeProject = QCloudHive.xcodeprojectByPath(Pathname.new("#{output}/#{name}").realpath.to_s)
115
+ xcconfigFiles.each { |f|
116
+ path = Pathname.new(projectDir).join(f.path)
117
+ config = Xcodeproj::Config.new(path)
118
+ linked = config.other_linker_flags[:libraries].to_a
119
+ L.info "#{config.other_linker_flags}"
120
+ frameworkLinked = config.other_linker_flags[:frameworks].to_a
121
+ L.info "linked #{linked}"
122
+ # unlinked.each { |e|
123
+ # linked.delete e
124
+ # willUnlink = UnlinkedModule(e, hiveXcodeProject)
125
+ # L.info "will unlink #{willUnlink}"
126
+ # linked -= willUnlink
127
+ # frameworkLinked -= willUnlink
128
+ # }
129
+ linked = linked.compact
130
+ frameworkLinked = frameworkLinked.compact
131
+ config.other_linker_flags[:libraries] = linked.to_set
132
+ config.other_linker_flags[:frameworks] = frameworkLinked.to_set
133
+ L.info "final linked #{linked}"
134
+ config.save_as(path)
135
+ }
136
+ #
137
+
138
+ productsDir = "Products"
139
+ productsDir = "#{projectDir}/#{productsDir}"
140
+ if not Pathname.new(productsDir).exist?
141
+ Pathname.new(productsDir).mkdir
142
+ end
143
+
144
+
145
+
146
+ buildCMD = BuildShell.new()
147
+ buildCMD.config = "Release"
148
+ buildCMD.productsDir = productsDir
149
+ buildCMD.other_cflags = "\"-fembed-bitcode\""
150
+ buildCMD.name = name
151
+ buildCMD.sdk = "iphoneos"
152
+ beginShell(name,buildCMD.to_cmd)
153
+
154
+
155
+ deviceFramework="#{productsDir}/Build/Products/#{buildCMD.config}-iphoneos/#{name}.framework"
156
+
157
+ if buildSimArch == true
158
+ buildCMD = BuildShell.new()
159
+ buildCMD.config = "Release"
160
+ buildCMD.productsDir = productsDir
161
+ buildCMD.other_cflags = "\"-fembed-bitcode\""
162
+ buildCMD.name = name
163
+ buildCMD.sdk = "iphonesimulator"
164
+
165
+ beginShell(name,buildCMD.to_cmd)
166
+ simFramework="#{productsDir}/Build/Products/#{buildCMD.config}-iphonesimulator/#{name}.framework"
167
+ Rake::sh " lipo -create #{deviceFramework}/#{name} #{simFramework}/#{name} -output #{deviceFramework}/#{name}"
168
+
169
+ end
170
+
171
+ puts "Copy frameworks"
172
+ outputFramework = "#{name}.framework"
173
+ outputFrameworkPath = Pathname.new(outputFramework)
174
+ if outputFrameworkPath.exist?
175
+ FileUtils.rm_rf(outputFrameworkPath.to_path)
176
+ end
177
+ Rake::sh "cp -rvf #{deviceFramework} #{outputFramework}"
178
+ Rake::sh "cp #{name}/.hivemodules #{outputFramework}/"
179
+ headersPath = Pathname.new("#{outputFramework}/Headers/")
180
+ if not headersPath.exist?
181
+ headersPath.mkdir
182
+ end
183
+ if Pathname("#{name}/Pods/Headers/Public").exist?
184
+ shell = "find #{name}/Pods/Headers/Public -name \"*.h\" -exec cp {} #{outputFramework}/Headers/ \\;"
185
+ Rake::sh shell
186
+ end
187
+ willRmBuild = opts[:i_rm_build]
188
+ if willRmBuild != false
189
+ FileUtils.rm_rf("#{name}")
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,75 @@
1
+
2
+ module QCloudHive
3
+ class GITURLDecoder
4
+ attr_reader :originURL
5
+ attr_reader :projectName
6
+ attr_reader :name
7
+
8
+ def initialize(originURL)
9
+ @originURL = originURL
10
+ if @originURL == nil
11
+ raise NameError("改地址为空!!!")
12
+ end
13
+ uri = URI(originURL)
14
+ uriPath = uri.path.split(".").first
15
+ if uriPath.start_with?("/")
16
+ uriPath= uriPath[1..uriPath.length]
17
+ end
18
+ name = uriPath.split("/").last
19
+ @projectName = uriPath
20
+ @name = name
21
+ end
22
+ def validate?()
23
+ if @originURL == nil
24
+ return false
25
+ end
26
+ if @name == nil
27
+ return false
28
+ end
29
+ if @projectName == nil
30
+ return false
31
+ end
32
+ return true
33
+ end
34
+ end
35
+ end
36
+ module Git
37
+ class Base
38
+ def clean?()
39
+ begin
40
+ if status.changed.count > 0
41
+ L.info("****************************")
42
+ L.info("changed #{status.changed}")
43
+ return false
44
+ end
45
+ if status.untracked.count >0
46
+ L.info("****************************")
47
+ L.info("untracked #{status.untracked}")
48
+ return false
49
+ end
50
+
51
+ if status.deleted.count > 0
52
+ L.info("****************************")
53
+ L.info("deleted #{status.deleted}")
54
+ return false
55
+ end
56
+
57
+ if status.added.count > 0
58
+ L.info("****************************")
59
+ L.info("added #{status.added}")
60
+ return false
61
+ end
62
+ rescue => err
63
+ puts "读取Git数据失败#{err}"
64
+ return false
65
+ end
66
+ return true
67
+ end
68
+ end
69
+
70
+ class Branch
71
+ def local?
72
+ full.start_with?("remotes") == false
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,69 @@
1
+ require 'gitlab'
2
+ require 'singleton'
3
+ require_relative "config.rb"
4
+ require_relative "utils.rb"
5
+
6
+ module QCloudHive
7
+ module CodeOA
8
+ def CodeOA.setup(token)
9
+ Gitlab.endpoint = "http://git.code.oa.com/api/v3"
10
+ Gitlab.private_token = token
11
+ end
12
+ def CodeOA.exist?(projectName)
13
+ project = existProjectByName?(projectName)
14
+ L.debug "project #{project}"
15
+ if project != nil
16
+ return true
17
+ else
18
+ return false
19
+ end
20
+ end
21
+
22
+ def CodeOA.branch(project, name)
23
+ begin
24
+ Gitlab.branch(project, name)
25
+ rescue Gitlab::Error::NotFound
26
+ return nil
27
+ end
28
+ end
29
+ def CodeOA.existProjectByName?(projectName)
30
+ projects = Gitlab.project_search(projectName)
31
+ L.info "所有项目 #{projects.count}"
32
+ aimProjects = projects.select{ |p|
33
+ L.debug "#{projectName} #{p.name} #{p.namespace.path} #{Config.team}"
34
+ p.name == projectName && p.namespace.path == Config.team
35
+ }
36
+ if aimProjects.count > 0
37
+ return aimProjects.first
38
+ else
39
+ return nil
40
+ end
41
+ end
42
+
43
+ def CodeOA.createProject(projectName)
44
+ project = CodeOA.existProjectByName?(projectName)
45
+ if project != nil
46
+ puts ("#{name}已经在CodeOA上存在,将不会在git.code.oa.com上再次新建改项目")
47
+ return project
48
+ else
49
+ Gitlab.create_project(projectName, {
50
+ :description => "#{projectName}的仓库",
51
+ :namespace_id => Config.namespaceID
52
+ })
53
+ CodeOA.existProjectByName?(projectName)
54
+ end
55
+ end
56
+
57
+ def CodeOA.branchs(project)
58
+ Gitlab.branches(project.id)
59
+ end
60
+
61
+ def CodeOA.empty?(project)
62
+ if Gitlab.branches(project.id).count == 0
63
+ true
64
+ else
65
+ false
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,346 @@
1
+ require 'nokogiri'
2
+ require 'uri'
3
+ require_relative "config.rb"
4
+
5
+ module QCloudHive
6
+ class ManifestProject
7
+ attr_accessor :remote
8
+ attr_accessor :path
9
+ attr_accessor :name
10
+ attr_accessor :moduleName
11
+ def initialize(remote, name ,path)
12
+ @remote = remote
13
+ @name = name
14
+ @path = path
15
+ @moduleName = name.split("/").last
16
+ #private values
17
+ @serverProject = nil
18
+ @podspec = nil
19
+ @git = nil
20
+ @podStorageSpec = nil
21
+ @localPath
22
+ end
23
+ def localPath
24
+ if @localPath == nil
25
+ root = Pathname(Config.projectRootDirectory)
26
+ @localPath = root.join(self.path).to_path
27
+ end
28
+ @localPath
29
+ end
30
+ def serverProject
31
+ if @serverProject.nil?
32
+ @serverProject = CodeOA.existProjectByName?(moduleName)
33
+ end
34
+ @serverProject
35
+ end
36
+ def podStorageSpec
37
+ if @podStorageSpec.nil?
38
+ L.info("search module #{moduleName}")
39
+ @podStorageSpec = HivePod.search(moduleName)
40
+
41
+ end
42
+ @podStorageSpec
43
+ end
44
+ def podspec
45
+ if @podspec.nil?
46
+ HivePod.podspecs.each { |pspec|
47
+ if pspec.name == self.moduleName
48
+ @podspec = pspec.podspec
49
+ end
50
+ }
51
+ if @podspec.nil?
52
+ @podspec = self.podStorageSpec
53
+ end
54
+ end
55
+ @podspec
56
+ end
57
+
58
+
59
+ def gitRepo
60
+ if @git.nil?
61
+ root = Pathname(Config.projectRootDirectory)
62
+ gitPath = root.join(self.path)
63
+ begin
64
+ @git = Git.open(gitPath)
65
+ rescue => err
66
+ puts "创建Git工程失败 #{gitPath} #{err}"
67
+ end
68
+ end
69
+ @git
70
+ end
71
+ def exsitLocal?
72
+ return self.gitRepo.nil? == false
73
+ end
74
+ def exsitPodRepo?
75
+ return self.podStorageSpec.nil? == false
76
+ end
77
+ def exsitServer?
78
+ return self.serverProject.nil? == false
79
+ end
80
+
81
+ def needReleasePod?
82
+ if exsitLocal?
83
+ return false
84
+ end
85
+ version = self.podspec.version.first
86
+ tag = gitRepo.tags.select { |e| e.name == version.to_s }.first
87
+ if tag.nil?
88
+ return true
89
+ end
90
+ master = gitRepo.branches["master"]
91
+ if tag.sha != master.gcommit.sha
92
+ return true
93
+ end
94
+ return false
95
+ end
96
+ end
97
+
98
+ class ProjectFeature
99
+ def initialize(project, branch)
100
+ @project = project
101
+ @branch = branch
102
+ #
103
+ @remoteBranch = nil
104
+ end
105
+ def remoteBranch
106
+ if @remoteBranch.nil?
107
+ @remoteBranch = CodeOA.branch(@project.serverProject.id, @branch.name)
108
+ end
109
+ @remoteBranch
110
+ end
111
+
112
+ def local?
113
+ if @branch.nil?
114
+ return false
115
+ end
116
+ localBranch.local?
117
+ end
118
+
119
+ def compareRemote
120
+ localSha = @branch.gcommit.sha
121
+ localDate = DateTime.parse(@branch.gcommit.committer_date.to_s)
122
+ remtoeDate = DateTime.parse(self.remoteBranch.commit.committed_date)
123
+ if self.remoteBranch.commit.id != localSha
124
+ return localDate <=> remtoeDate
125
+ end
126
+ return 0
127
+ end
128
+
129
+ def compareMaster
130
+ if @branch.name == "master"
131
+ return 0
132
+ end
133
+ master = @project.gitRepo.branches["master"]
134
+ localDate = DateTime.parse(@branch.gcommit.committer_date.to_s)
135
+ masterLocalDate = master.gcommit.committer_date
136
+ masterDate = DateTime.parse(masterLocalDate.to_s)
137
+ localDate <=> masterDate
138
+ end
139
+ end
140
+
141
+ class ManifestRemote
142
+ attr_accessor :name
143
+ attr_accessor :fetch
144
+
145
+ def initialize(name, fetch)
146
+ @name = name
147
+ @fetch = fetch
148
+ end
149
+ end
150
+
151
+ class ManifestDefault
152
+ attr_accessor :revision
153
+ attr_accessor :remote
154
+ attr_accessor :sync_j
155
+ def initialize
156
+ @revision = "master"
157
+ @remote = "origin"
158
+ @sync_j = "16"
159
+ end
160
+ end
161
+
162
+ class Manifest
163
+ attr_accessor :projects
164
+ attr_accessor :remotes
165
+ attr_accessor :default
166
+
167
+ def initialize(filePath)
168
+ @manifestPath = filePath
169
+ @doc = Nokogiri::XML(File.open(filePath))
170
+ @default = ManifestDefault.new
171
+ @projects = []
172
+ @doc.xpath("//project").each { |p|
173
+ remote = p.attribute("remote").value
174
+ name = p.attribute("name").value
175
+ if name.start_with?("/")
176
+ name= name[1..name.length]
177
+ end
178
+ path = p.attribute("path").value
179
+ project = ManifestProject.new(remote, name, path)
180
+ @projects << project
181
+ L.debug project
182
+ }
183
+
184
+ @remotes = []
185
+ @doc.xpath("//remote").each { |r|
186
+ name = r.attribute("name").value
187
+ fetch = r.attribute("fetch").value
188
+ if not fetch.end_with?("/")
189
+ fetch = fetch+"/"
190
+ end
191
+ remote = ManifestRemote.new(name, fetch)
192
+ @remotes << remote
193
+ }
194
+ end
195
+
196
+ def addModule(url, path)
197
+ uri = URI(url)
198
+ host = uri.host
199
+ scheme = uri.scheme
200
+ remote = nil
201
+ uriPath = uri.path.split(".").first
202
+ if uriPath.start_with?("/")
203
+ uriPath= uriPath[1..uriPath.length]
204
+ end
205
+ name = uriPath.split("/").last
206
+ @projects.each { |p|
207
+ if p.name == uriPath
208
+ return @projects
209
+ end
210
+ }
211
+ @remotes.each { |r|
212
+ rfetch = URI(r.fetch)
213
+ if rfetch.host == host and rfetch.scheme == scheme
214
+ remote = r.name
215
+ end
216
+ }
217
+ projectPath = "#{name}"
218
+ if path != nil
219
+ if path.start_with?("/")
220
+ path = path[1..-1]
221
+ end
222
+ if path.end_with?("/")
223
+ projectPath = "#{path}#{name}"
224
+ else
225
+ if path.length > 0
226
+ projectPath = "#{path}/#{name}"
227
+ else
228
+ projectPath = "#{name}"
229
+ end
230
+ end
231
+ end
232
+ remote = ManifestProject.new(remote, uriPath ,projectPath)
233
+ @projects << remote
234
+ end
235
+
236
+ def existModule?(name)
237
+ @projects.select{ |p|
238
+ if p.name.start_with?(Config.team)
239
+ p.name == Config.team+"/#{name}"
240
+ else
241
+ p.name == name
242
+ end
243
+ }.count > 0
244
+ end
245
+
246
+ def moduleByName(name)
247
+ @projects.each { |p|
248
+ L.info p.name
249
+ }
250
+ @projects.select{ |p|
251
+ if p.name.start_with?(Config.team)
252
+ p.name == Config.team+"/#{name}"
253
+ else
254
+ p.name == name
255
+ end
256
+ }.first
257
+ end
258
+
259
+ def deleteModule(url)
260
+ uri = URI(url)
261
+ uriPath = uri.path.split(".").first
262
+ if uriPath.start_with?("/")
263
+ uriPath= uriPath[1..uriPath.length]
264
+ end
265
+ L.debug "#{@projects}"
266
+ @projects=@projects.select{ |e|
267
+ e.name != uriPath
268
+ }
269
+ L.debug "#{@projects}"
270
+ end
271
+
272
+ def deleteModuleByName(name)
273
+ L.debug "#{@projects}"
274
+ @projects=@projects.select{ |e|
275
+ e.moduleName != name
276
+ }
277
+ L.debug "#{@projects}"
278
+ end
279
+
280
+ def toXML
281
+ doc = Nokogiri::XML('''<?xml version="1.0" encoding="UTF-8"?><manifest></manifest>''')
282
+ manifest = doc.xpath("//manifest").first
283
+
284
+ @remotes.each { |r|
285
+ ele = Nokogiri::XML::Element.new("remote", doc)
286
+ ele.set_attribute("name", r.name)
287
+ ele.set_attribute("fetch", r.fetch)
288
+ manifest.add_child(ele)
289
+ }
290
+
291
+ default = Nokogiri::XML::Element.new("default", doc)
292
+ default.set_attribute("revision", @default.revision)
293
+ default.set_attribute("remote", @default.remote)
294
+ default.set_attribute("sync-j", @default.sync_j)
295
+ manifest.add_child(default)
296
+
297
+ @projects.each { |r|
298
+ ele =Nokogiri::XML::Element.new("project", doc)
299
+ ele.set_attribute("name",r.name)
300
+ ele.set_attribute("remote" ,r.remote )
301
+ ele.set_attribute("path" ,r.path)
302
+ manifest.add_child(ele)
303
+ }
304
+ return doc.to_s
305
+ end
306
+
307
+ def flushStorage
308
+ File.open(@manifestPath, "w") { |f|
309
+ f.write toXML
310
+ }
311
+ end
312
+ def remoteByName(name)
313
+ @remotes.select { |e| e.name == name }.first
314
+ end
315
+ def sourceURLByModuleName(name)
316
+ L.debug "#{@projects}"
317
+ moduleSpec = @projects.select{ |e|
318
+ e.moduleName != name
319
+ }.first
320
+ if moduleSpec.nil?
321
+ return nil
322
+ end
323
+ remote = remoteByName(moduleSpec.remote)
324
+ return "#{remote.fetch}#{moduleSpec.name}"
325
+ end
326
+ end
327
+
328
+
329
+
330
+ def QCloudHive.syncManifest
331
+ repoRootPath = Config.repoRoot
332
+ manifestsPath=repoRootPath+"./manifests/"
333
+ cmd = ""
334
+ cmd = addCMD(cmd,"cd #{manifestsPath}")
335
+ cmd = addCMD(cmd, "git add .")
336
+ cmd = addCMD(cmd, "git commit -m \"Project Edited\"")
337
+ cmd = addCMD(cmd, "git checkout default")
338
+ cmd = addCMD(cmd, "git push origin HEAD:default")
339
+ cmd = addCMD(cmd, "git checkout master")
340
+ cmd = addCMD(cmd, "git merge default")
341
+ cmd = addCMD(cmd, "git push origin HEAD:master")
342
+ cmd = addCMD(cmd, "git checkout default")
343
+ L.debug cmd
344
+ Rake::sh cmd
345
+ end
346
+ end