synx 0.0.2
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.
- checksums.yaml +7 -0
- data/.gitignore +46 -0
- data/.travis.yml +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +70 -0
- data/Rakefile +2 -0
- data/bin/synx +18 -0
- data/lib/synx.rb +13 -0
- data/lib/synx/abstract_object.rb +44 -0
- data/lib/synx/pbx_file_reference.rb +70 -0
- data/lib/synx/pbx_group.rb +126 -0
- data/lib/synx/pbx_native_target.rb +15 -0
- data/lib/synx/pbx_variant_group.rb +20 -0
- data/lib/synx/project.rb +100 -0
- data/lib/synx/tabber.rb +35 -0
- data/lib/synx/version.rb +3 -0
- data/spec/dummy/dummy.xcodeproj/project.pbxproj +534 -0
- data/spec/dummy/dummy.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
- data/spec/dummy/dummy/AlreadySynced/Core Data.xcdatamodeld/.xccurrentversion +8 -0
- data/spec/dummy/dummy/AlreadySynced/Core Data.xcdatamodeld/Core Data 2.xcdatamodel/contents +4 -0
- data/spec/dummy/dummy/AlreadySynced/Core Data.xcdatamodeld/Core Data 3.xcdatamodel/contents +4 -0
- data/spec/dummy/dummy/AlreadySynced/Core Data.xcdatamodeld/Core Data 4.xcdatamodel/contents +4 -0
- data/spec/dummy/dummy/AlreadySynced/Core Data.xcdatamodeld/Core Data.xcdatamodel/contents +4 -0
- data/spec/dummy/dummy/AlreadySynced/FolderNotInXcodeProj/AnotherFileNotInXcodeProj.h +0 -0
- data/spec/dummy/dummy/AlreadySynced/FolderNotInXcodeProj/NSObject+abc.h +13 -0
- data/spec/dummy/dummy/AlreadySynced/FolderNotInXcodeProj/NSObject+abc.m +13 -0
- data/spec/dummy/dummy/AlreadySynced/FolderNotInXcodeProj/Wowwww.h +13 -0
- data/spec/dummy/dummy/AlreadySynced/FolderNotInXcodeProj/Wowwww.m +13 -0
- data/spec/dummy/dummy/AlreadySynced/Woot.h +13 -0
- data/spec/dummy/dummy/AlreadySynced/Woot.m +13 -0
- data/spec/dummy/dummy/AlreadySynced/stuff.xml +0 -0
- data/spec/dummy/dummy/FileNotInXcodeProj.h +0 -0
- data/spec/dummy/dummy/ManyFiles.h +13 -0
- data/spec/dummy/dummy/ManyFiles.m +13 -0
- data/spec/dummy/dummy/Wow.h +13 -0
- data/spec/dummy/dummy/Wow.m +13 -0
- data/spec/dummy/dummy/data.json +0 -0
- data/spec/dummy/dummy/dummy-Prefix.pch +9 -0
- data/spec/dummy/dummy/dummy.h +13 -0
- data/spec/dummy/dummy/dummy.m +13 -0
- data/spec/dummy/dummy/image-not-in-xcodeproj.png +0 -0
- data/spec/dummy/dummy/image.png +0 -0
- data/spec/dummy/dummyTests/dummyTests-Info.plist +22 -0
- data/spec/dummy/dummyTests/dummyTests-prefix.pch +15 -0
- data/spec/dummy/dummyTests/dummyTests.m +34 -0
- data/spec/dummy/dummyTests/en.lproj/InfoPlist.strings +2 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/synx/expected_file_structure.yml +44 -0
- data/spec/synx/expected_group_structure.yml +37 -0
- data/spec/synx/project_spec.rb +218 -0
- data/spec/synx/tabber_spec.rb +64 -0
- data/synx.gemspec +33 -0
- metadata +251 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 38ba9b910838a673bb8e0199f562abae2e140126
|
4
|
+
data.tar.gz: f9a300779af02f69433fa27e033cad0d293d97a6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4d9fe16a2d37b84481703837be549b1c5a0ba4156d9968675d00ed69dc98917cbaef6ea5ec04db1076f6bb21555c03abf14e27fa99fd28024379fd2dbf4ce63d
|
7
|
+
data.tar.gz: c7ce4e21c6e7768e3ff765aa7a9332169593477a761ffa1d2234b0d8df69c6276752ba712a898e8d5f89fb525be7c92c8a86ee62ad0accfbfd61effce33d8e2f
|
data/.gitignore
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.yardoc
|
6
|
+
Gemfile.lock
|
7
|
+
InstalledFiles
|
8
|
+
_yardoc
|
9
|
+
coverage
|
10
|
+
doc/
|
11
|
+
lib/bundler/man
|
12
|
+
pkg
|
13
|
+
rdoc
|
14
|
+
spec/reports
|
15
|
+
test/tmp
|
16
|
+
test/version_tmp
|
17
|
+
tmp
|
18
|
+
*.bundle
|
19
|
+
*.so
|
20
|
+
*.o
|
21
|
+
*.a
|
22
|
+
mkmf.log
|
23
|
+
|
24
|
+
# Xcode
|
25
|
+
#
|
26
|
+
build/
|
27
|
+
*.pbxuser
|
28
|
+
!default.pbxuser
|
29
|
+
*.mode1v3
|
30
|
+
!default.mode1v3
|
31
|
+
*.mode2v3
|
32
|
+
!default.mode2v3
|
33
|
+
*.perspectivev3
|
34
|
+
!default.perspectivev3
|
35
|
+
xcuserdata
|
36
|
+
*.xccheckout
|
37
|
+
*.moved-aside
|
38
|
+
DerivedData
|
39
|
+
*.hmap
|
40
|
+
*.ipa
|
41
|
+
*.xcuserstate
|
42
|
+
*.DS_Store
|
43
|
+
|
44
|
+
|
45
|
+
# Spec
|
46
|
+
spec/test_dummy/
|
data/.travis.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
language: objective-c
|
2
|
+
script: bundle exec rspec
|
3
|
+
|
4
|
+
# Sets Travis to run the Ruby specs on OS X machines which are required to
|
5
|
+
# build the native extensions of Xcodeproj.
|
6
|
+
|
7
|
+
env:
|
8
|
+
- RVM_RUBY_VERSION=system
|
9
|
+
- RVM_RUBY_VERSION=2.1.1
|
10
|
+
|
11
|
+
before_install:
|
12
|
+
- curl http://curl.haxx.se/ca/cacert.pem -o /usr/local/share/cacert.pem
|
13
|
+
- source ~/.rvm/scripts/rvm
|
14
|
+
- if [[ $RVM_RUBY_VERSION != 'system' ]]; then rvm install $RVM_RUBY_VERSION; fi
|
15
|
+
- rvm use $RVM_RUBY_VERSION
|
16
|
+
- if [[ $RVM_RUBY_VERSION == 'system' ]]; then export ARCHFLAGS=-Wno-error=unused-command-line-argument-hard-error-in-future; fi
|
17
|
+
- if [[ $RVM_RUBY_VERSION == 'system' ]]; then sudo gem install bundler --no-ri --no-rdoc; else gem install bundler --no-ri --no-rdoc; fi
|
18
|
+
|
19
|
+
install:
|
20
|
+
- bundle install --without=documentation --path ./travis_bundle_dir
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Mark Larsen
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
[](http://badge.fury.io/rb/synx)
|
2
|
+

|
3
|
+
|
4
|
+

|
5
|
+
|
6
|
+
A command-line tool that automagically reorganizes your Xcode project folder.
|
7
|
+
|
8
|
+

|
9
|
+
|
10
|
+
##### Xcode
|
11
|
+
|
12
|
+

|
13
|
+
|
14
|
+
##### Finder
|
15
|
+
|
16
|
+

|
17
|
+
|
18
|
+
## Installation
|
19
|
+
|
20
|
+
Add this line to your application's Gemfile:
|
21
|
+
|
22
|
+
gem 'synx'
|
23
|
+
|
24
|
+
And then execute:
|
25
|
+
|
26
|
+
$ bundle
|
27
|
+
|
28
|
+
Or install it yourself as:
|
29
|
+
|
30
|
+
$ gem install synx
|
31
|
+
|
32
|
+
## Usage
|
33
|
+
|
34
|
+
### Basic
|
35
|
+
|
36
|
+
**WARNING: Make sure that your project is backed up through source control before doing anything**
|
37
|
+
|
38
|
+
Execute the command on your project to have it reorganize the files on the file system:
|
39
|
+
|
40
|
+
$ synx path/to/my/project.xcodeproj
|
41
|
+
|
42
|
+
It may have confused cocoapods. Pod install, if you use them:
|
43
|
+
|
44
|
+
$ pod
|
45
|
+
|
46
|
+
You're good to go!
|
47
|
+
|
48
|
+
### Advanced
|
49
|
+
|
50
|
+
Synx supports the following options:
|
51
|
+
|
52
|
+
```
|
53
|
+
--prune, -p remove source files and image resources that are not referenced by the the xcode project
|
54
|
+
--no-default-exclusions doesn't use the default exclusions of /Libraries, /Frameworks, and /Products
|
55
|
+
--exclusion, -e EXCLUSION ignore an Xcode group while syncing
|
56
|
+
```
|
57
|
+
|
58
|
+
OCMock, for example, could have done:
|
59
|
+
|
60
|
+
$ synx -p -e=OCMock/Core -e=OCKMockTests Source/OCMock.xcodeproj
|
61
|
+
|
62
|
+
if they wanted to not sync the `OCMock/Core` and `OCMockTests` groups, and also remove (`-p`) any image/source files found by Synx that weren't ever referenced by any groups in Xcode.
|
63
|
+
|
64
|
+
## Contributing
|
65
|
+
|
66
|
+
1. Fork it ( https://github.com/[my-github-username]/synx/fork )
|
67
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
68
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
69
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
70
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
data/bin/synx
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'clamp'
|
4
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'synx')
|
5
|
+
|
6
|
+
Clamp do
|
7
|
+
|
8
|
+
parameter "xcodeproj", "Path to the xcodeproj", :attribute_name => :xcodeproj_path
|
9
|
+
option ["--prune", "-p"], :flag, "remove source files and image resources that are not referenced by the the xcode project"
|
10
|
+
option "--no-default-exclusions", :flag, "doesn't use the default exclusions of /Libraries, /Frameworks, and /Products"
|
11
|
+
option ["--exclusion", "-e"], "EXCLUSION", "ignore an Xcode group while syncing", :multivalued => true
|
12
|
+
|
13
|
+
def execute
|
14
|
+
project = Synx::Project.open(xcodeproj_path)
|
15
|
+
project.sync(:prune => prune?, :no_default_exclusions => no_default_exclusions?, :group_exclusions => exclusion_list)
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
data/lib/synx.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "synx/version"
|
2
|
+
require "synx/project"
|
3
|
+
require "synx/pbx_file_reference"
|
4
|
+
require "synx/pbx_group"
|
5
|
+
require "synx/abstract_object"
|
6
|
+
require "synx/pbx_native_target"
|
7
|
+
require "synx/pbx_variant_group"
|
8
|
+
require "synx/tabber"
|
9
|
+
|
10
|
+
require "colored"
|
11
|
+
|
12
|
+
module Synx
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module Xcodeproj
|
4
|
+
class Project
|
5
|
+
module Object
|
6
|
+
class AbstractObject
|
7
|
+
|
8
|
+
def basename
|
9
|
+
name || path || Pathname(real_path).basename.to_s
|
10
|
+
end
|
11
|
+
|
12
|
+
def referring_groups
|
13
|
+
referrers.select { |ref| ref.instance_of?(Xcodeproj::Project::Object::PBXGroup) }
|
14
|
+
end
|
15
|
+
|
16
|
+
def work_pathname
|
17
|
+
# hierarchy path has a leading '/' that will break path concatenation
|
18
|
+
@work_pathname ||= project.work_root_pathname + hierarchy_path[1..-1]
|
19
|
+
end
|
20
|
+
|
21
|
+
def ensure_internal_consistency(group)
|
22
|
+
@removed_from_groups = []
|
23
|
+
if referring_groups.count > 1
|
24
|
+
# Files should only have one referring group -- this is an internal consistency issue if there is more than 1.
|
25
|
+
# Just remove all referring groups but the one we're syncing with
|
26
|
+
|
27
|
+
referring_groups.each do |rg|
|
28
|
+
unless rg == group
|
29
|
+
rg.remove_reference(self) unless rg == group
|
30
|
+
@removed_from_groups << rg.hierarchy_path
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def sync(group)
|
38
|
+
raise NotImplementedError
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module Xcodeproj
|
4
|
+
class Project
|
5
|
+
module Object
|
6
|
+
class PBXFileReference
|
7
|
+
|
8
|
+
def sync(group)
|
9
|
+
if should_sync?
|
10
|
+
if should_move?
|
11
|
+
FileUtils.mv(real_path.to_s, group.work_pathname.to_s)
|
12
|
+
# TODO: move out to abstract_object
|
13
|
+
self.source_tree = "<group>"
|
14
|
+
self.path = real_path.basename.to_s
|
15
|
+
else
|
16
|
+
# Don't move this file around -- it's not even inside the structure. Just fix the relative reference
|
17
|
+
self.path = real_path.relative_path_from((project.work_pathname_to_pathname(group.work_pathname))).to_s
|
18
|
+
end
|
19
|
+
change_build_settings_reference
|
20
|
+
|
21
|
+
output
|
22
|
+
else
|
23
|
+
Synx::Tabber.puts "skipped #{basename}".red
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def output
|
28
|
+
build_settings_ammended = "(build settings ammended: #{@setting_keys_changed.join(", ")})" if @setting_keys_changed.count > 0
|
29
|
+
removed_from_groups = "(had multiple parent groups, removed from groups: #{@removed_from_groups.join(", ")})" if @removed_from_groups.count > 0
|
30
|
+
str_output = "#{basename} #{build_settings_ammended} #{removed_from_groups}"
|
31
|
+
str_output = str_output.yellow if removed_from_groups || build_settings_ammended
|
32
|
+
Synx::Tabber.puts str_output
|
33
|
+
end
|
34
|
+
|
35
|
+
def should_sync?
|
36
|
+
# Don't sync files that don't exist or are Apple/Build stuff
|
37
|
+
real_path.exist? && !(real_path.to_s =~ /^\$\{(SDKROOT|DEVELOPER_DIR|BUILT_PRODUCTS_DIR)\}/)
|
38
|
+
end
|
39
|
+
private :should_sync?
|
40
|
+
|
41
|
+
def should_move?
|
42
|
+
# Don't move these files around -- they're not even inside the structure. Just fix the relative references.
|
43
|
+
!(real_path.to_s =~ /\.xcodeproj$/) && project.pathname_is_inside_root_pathname?(real_path)
|
44
|
+
end
|
45
|
+
private :should_move?
|
46
|
+
|
47
|
+
# Fixes things like pch, info.plist references being changed
|
48
|
+
def change_build_settings_reference
|
49
|
+
@setting_keys_changed = []
|
50
|
+
return unless basename =~ /\.(pch|plist)$/
|
51
|
+
|
52
|
+
project.targets.each do |t|
|
53
|
+
t.each_build_settings do |bs|
|
54
|
+
["INFOPLIST_FILE", "GCC_PREFIX_HEADER"].each do |setting_key|
|
55
|
+
setting_value = bs[setting_key]
|
56
|
+
if setting_value == real_path.relative_path_from(project.root_pathname).to_s
|
57
|
+
bs[setting_key] = hierarchy_path[1..-1]
|
58
|
+
@setting_keys_changed << setting_key
|
59
|
+
end
|
60
|
+
end if bs
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
@setting_keys_changed.uniq!
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
require 'xcodeproj'
|
2
|
+
|
3
|
+
module Xcodeproj
|
4
|
+
class Project
|
5
|
+
module Object
|
6
|
+
class PBXGroup
|
7
|
+
|
8
|
+
def sync(group)
|
9
|
+
ensure_internal_consistency(group)
|
10
|
+
if excluded_from_sync?
|
11
|
+
Synx::Tabber.puts "#{basename}/ (excluded)".yellow
|
12
|
+
else
|
13
|
+
Synx::Tabber.puts "#{basename}/".green
|
14
|
+
Synx::Tabber.increase
|
15
|
+
|
16
|
+
squash_duplicate_file_references
|
17
|
+
work_pathname.mkpath
|
18
|
+
files.each { |pbx_file| pbx_file.sync(self) }
|
19
|
+
all_groups.each { |group| group.sync(self) }
|
20
|
+
sync_path
|
21
|
+
|
22
|
+
Synx::Tabber.decrease
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def excluded_from_sync?
|
27
|
+
project.group_exclusions.include?(hierarchy_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def move_entries_not_in_xcodeproj
|
31
|
+
if excluded_from_sync?
|
32
|
+
Synx::Tabber.puts "#{basename}/ (excluded)".yellow
|
33
|
+
else
|
34
|
+
Synx::Tabber.puts "#{basename}/".green
|
35
|
+
Synx::Tabber.increase
|
36
|
+
Dir[real_path.to_s + "/*"].each do |entry|
|
37
|
+
entry_pathname = real_path + entry
|
38
|
+
unless has_entry?(entry_pathname)
|
39
|
+
handle_unused_entry(entry_pathname)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
all_groups.each(&:move_entries_not_in_xcodeproj)
|
43
|
+
Synx::Tabber.decrease
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def sync_path
|
48
|
+
self.path = basename
|
49
|
+
self.source_tree = "<group>"
|
50
|
+
end
|
51
|
+
private :sync_path
|
52
|
+
|
53
|
+
def has_entry?(entry_pathname)
|
54
|
+
%W(. ..).include?(entry_pathname.basename.to_s) || children.any? do |child|
|
55
|
+
child.real_path.cleanpath == entry_pathname.realpath.cleanpath
|
56
|
+
end
|
57
|
+
end
|
58
|
+
private :has_entry?
|
59
|
+
|
60
|
+
def all_groups
|
61
|
+
groups | version_groups | variant_groups
|
62
|
+
end
|
63
|
+
|
64
|
+
def variant_groups
|
65
|
+
children.select { |child| child.instance_of?(Xcodeproj::Project::Object::PBXVariantGroup) }
|
66
|
+
end
|
67
|
+
private :variant_groups
|
68
|
+
|
69
|
+
def handle_unused_entry(entry_pathname)
|
70
|
+
if entry_pathname.directory?
|
71
|
+
project.pathname_to_work_pathname(entry_pathname).mkdir
|
72
|
+
# recurse
|
73
|
+
Synx::Tabber.puts entry_pathname.basename.to_s.green
|
74
|
+
Synx::Tabber.increase
|
75
|
+
entry_pathname.children.each { |child| handle_unused_entry(child) }
|
76
|
+
Synx::Tabber.decrease
|
77
|
+
elsif entry_pathname.file?
|
78
|
+
handle_unused_file(entry_pathname)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
private :handle_unused_entry
|
82
|
+
|
83
|
+
def handle_unused_file(file_pathname)
|
84
|
+
prune_file_extensions = %W(.h .m .xib .mm .c .png .jpg .jpeg)
|
85
|
+
is_file_to_prune = prune_file_extensions.include?(file_pathname.extname.downcase)
|
86
|
+
|
87
|
+
if is_file_to_prune && project.prune
|
88
|
+
Synx::Tabber.puts "#{file_pathname.basename} (removed source/image file that is not referenced by the Xcode project)".red
|
89
|
+
return
|
90
|
+
elsif !project.prune || !is_file_to_prune
|
91
|
+
FileUtils.mv(file_pathname.realpath, project.pathname_to_work_pathname(file_pathname.parent).realpath)
|
92
|
+
if is_file_to_prune
|
93
|
+
Synx::Tabber.puts "#{file_pathname.basename} (source/image file that is not referenced by the Xcode project)".yellow
|
94
|
+
else
|
95
|
+
Synx::Tabber.puts file_pathname.basename
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
private :handle_unused_file
|
100
|
+
|
101
|
+
def squash_duplicate_file_references
|
102
|
+
files.each { |f| f.ensure_internal_consistency(self) }
|
103
|
+
|
104
|
+
grouped_by_path = files.group_by do |file|
|
105
|
+
file.real_path.cleanpath
|
106
|
+
end
|
107
|
+
|
108
|
+
duplicates = grouped_by_path.select do |file_path, files|
|
109
|
+
files.count > 1
|
110
|
+
end
|
111
|
+
|
112
|
+
duplicates.each do |file_path, files|
|
113
|
+
file = files.last
|
114
|
+
# Removes all references (files array)
|
115
|
+
remove_reference(file)
|
116
|
+
# Adds just one back
|
117
|
+
self << file
|
118
|
+
Synx::Tabber.puts "#{file.basename} (removed duplicate reference)".red
|
119
|
+
end
|
120
|
+
end
|
121
|
+
private :squash_duplicate_file_references
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|