milkode 0.9.2 → 0.9.3
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.
- data/HISTORY.ja.rdoc +23 -0
- data/HISTORY.rdoc +20 -0
- data/VERSION +1 -1
- data/bin/gmilk +1 -1
- data/bin/milk +1 -1
- data/lib/milkode/cdstk/cdstk.rb +244 -131
- data/lib/milkode/cdweb/app.rb +49 -2
- data/lib/milkode/cdweb/lib/database.rb +24 -0
- data/lib/milkode/cdweb/public/images/view-refresh-4.png +0 -0
- data/lib/milkode/cdweb/public/images/waiting.gif +0 -0
- data/lib/milkode/cdweb/public/js/milkode.js +25 -0
- data/lib/milkode/cdweb/views/layout.haml +1 -0
- data/lib/milkode/cli.rb +27 -4
- data/lib/milkode/common/grenfiletest.rb +1 -1
- data/lib/milkode/common/plang_detector.rb +111 -0
- data/lib/milkode/common/util.rb +10 -1
- data/lib/milkode/database/groonga_database.rb +4 -4
- data/lib/milkode/database/updater.rb +242 -0
- data/milkode.gemspec +10 -2
- data/test/data/ignore_test/.gitignore +1 -0
- data/test/data/ignore_test/a.txt +1 -0
- data/test/test_cli.rb +2 -1
- data/test/test_plang_detector.rb +32 -0
- data/test/test_updater.rb +121 -0
- metadata +12 -4
data/HISTORY.ja.rdoc
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
=== 0.9.3 2012/10/06
|
2
|
+
|
3
|
+
* milk web
|
4
|
+
* Webインターフェースからのアップデートに対応
|
5
|
+
|
6
|
+
* milk info
|
7
|
+
* ファイル数、行数、breakdown(種類別) 表示
|
8
|
+
* テーブル形式で表示 (-t)
|
9
|
+
* 全てのパッケージを表示 (-a)
|
10
|
+
* 種類別詳細表示 (-b)
|
11
|
+
|
12
|
+
* milk
|
13
|
+
* milk plugins: add Milkode_Sublime
|
14
|
+
* milk add: --no-auto-ignore の短縮形 -n を追加
|
15
|
+
|
16
|
+
* database
|
17
|
+
* Add Updater
|
18
|
+
* IgnoreChecker の require忘れ
|
19
|
+
|
20
|
+
* common
|
21
|
+
* grenfiletest.rb: Add ignore suffix
|
22
|
+
* Add PlgnDetector
|
23
|
+
|
1
24
|
=== 0.9.2 2012/09/07
|
2
25
|
|
3
26
|
* etc
|
data/HISTORY.rdoc
CHANGED
@@ -1,3 +1,23 @@
|
|
1
|
+
=== 0.9.3 2012/10/06
|
2
|
+
|
3
|
+
* milk web
|
4
|
+
* Update from web interface
|
5
|
+
|
6
|
+
* milk info
|
7
|
+
* file_count, line_count, breakdown
|
8
|
+
* -a(--all), -t(--table), -b(--breakdown)
|
9
|
+
|
10
|
+
* milk
|
11
|
+
* milk plugins: add Milkode_Sublime
|
12
|
+
* milk add: add -n(--no-auto-ignore)
|
13
|
+
|
14
|
+
* database
|
15
|
+
* Add Updater
|
16
|
+
|
17
|
+
* common
|
18
|
+
* grenfiletest.rb: Add ignore suffix
|
19
|
+
* Add PlgnDetector
|
20
|
+
|
1
21
|
=== 0.9.2 2012/09/07
|
2
22
|
|
3
23
|
* etc
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.9.
|
1
|
+
0.9.3
|
data/bin/gmilk
CHANGED
data/bin/milk
CHANGED
data/lib/milkode/cdstk/cdstk.rb
CHANGED
@@ -23,6 +23,8 @@ require 'milkode/common/ignore_checker'
|
|
23
23
|
require 'milkode/database/groonga_database'
|
24
24
|
require 'milkode/database/document_record'
|
25
25
|
require 'milkode/common/array_diff'
|
26
|
+
require 'milkode/database/updater'
|
27
|
+
require 'milkode/common/plang_detector'
|
26
28
|
|
27
29
|
module Milkode
|
28
30
|
class IgnoreError < RuntimeError ; end
|
@@ -386,11 +388,12 @@ module Milkode
|
|
386
388
|
|
387
389
|
@out.puts str
|
388
390
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
391
|
+
if Util.pipe? $stdout
|
392
|
+
if args.empty?
|
393
|
+
milkode_info
|
394
|
+
else
|
395
|
+
list_info(match_p) unless match_p.empty?
|
396
|
+
end
|
394
397
|
end
|
395
398
|
end
|
396
399
|
|
@@ -638,8 +641,207 @@ EOF
|
|
638
641
|
end
|
639
642
|
end
|
640
643
|
|
641
|
-
def info
|
642
|
-
|
644
|
+
def info(args, options)
|
645
|
+
db_open
|
646
|
+
|
647
|
+
if options[:all]
|
648
|
+
info_format(@yaml.contents, select_format(options, :table))
|
649
|
+
milkode_info
|
650
|
+
return
|
651
|
+
end
|
652
|
+
|
653
|
+
packages = find_packages(args)
|
654
|
+
packages.compact!
|
655
|
+
return if (packages.empty?)
|
656
|
+
|
657
|
+
info_format(packages, select_format(options, :detail))
|
658
|
+
end
|
659
|
+
|
660
|
+
def select_format(options, default_value)
|
661
|
+
format = default_value
|
662
|
+
format = :detail if options[:detail]
|
663
|
+
format = :table if options[:table]
|
664
|
+
format = :breakdown if options[:breakdown]
|
665
|
+
format = :unknown if options[:unknown]
|
666
|
+
format
|
667
|
+
end
|
668
|
+
|
669
|
+
def info_format(packages, format)
|
670
|
+
case format
|
671
|
+
when :detail
|
672
|
+
info_format_detail(packages)
|
673
|
+
when :table
|
674
|
+
info_format_table(packages)
|
675
|
+
when :breakdown
|
676
|
+
info_format_breakdown(packages)
|
677
|
+
when :unknown
|
678
|
+
info_format_unknown(packages)
|
679
|
+
end
|
680
|
+
end
|
681
|
+
|
682
|
+
def info_format_detail(packages)
|
683
|
+
packages.each_with_index do |package, index|
|
684
|
+
records = package_records(package.name)
|
685
|
+
|
686
|
+
r = []
|
687
|
+
r.push "Name: #{package.name}"
|
688
|
+
r.push "Ignore: #{package.ignore}" unless package.ignore.empty?
|
689
|
+
r.push "Options: #{package.options}" unless package.options.empty?
|
690
|
+
r.push "Records: #{records.size}"
|
691
|
+
r.push "Breakdown: #{breakdown_shorten(records)}"
|
692
|
+
r.push "Linecount: #{linecount_total(records)}"
|
693
|
+
r.push ""
|
694
|
+
|
695
|
+
@out.puts if index != 0
|
696
|
+
@out.puts r.join("\n")
|
697
|
+
end
|
698
|
+
end
|
699
|
+
|
700
|
+
NAME = 'Name'
|
701
|
+
TOTAL = 'Total'
|
702
|
+
|
703
|
+
def info_format_table(packages)
|
704
|
+
max = packages.map{|p| p.name.length}.max
|
705
|
+
max = NAME.length if max < NAME.length
|
706
|
+
|
707
|
+
@out.puts <<EOF.chomp
|
708
|
+
#{NAME.ljust(max)} Records Linecount
|
709
|
+
#{'=' * max}========================
|
710
|
+
EOF
|
711
|
+
|
712
|
+
packages.each do |package|
|
713
|
+
records = package_records(package.name)
|
714
|
+
@out.puts "#{package.name.ljust(max)} #{records.size.to_s.rjust(10)} #{linecount_total(records).to_s.rjust(10)}"
|
715
|
+
end
|
716
|
+
end
|
717
|
+
|
718
|
+
def info_format_breakdown(packages)
|
719
|
+
packages.each_with_index do |package, index|
|
720
|
+
records = package_records(package.name)
|
721
|
+
plangs = sorted_plangs(records)
|
722
|
+
|
723
|
+
# column1's width
|
724
|
+
plang_names = plangs.map{|v| v[0]}
|
725
|
+
max = (plang_names + [package.name, TOTAL]).map{|name| name.length}.max
|
726
|
+
|
727
|
+
@out.puts if index != 0
|
728
|
+
@out.puts <<EOF.chomp
|
729
|
+
#{package.name.ljust(max)} files rate
|
730
|
+
#{'=' * max}=============
|
731
|
+
#{breakdown_detail(package_records(package.name), max)}
|
732
|
+
#{'-' * max}-------------
|
733
|
+
#{sprintf("%-#{max}s %5d %3d%%", TOTAL, records.size, 100)}
|
734
|
+
EOF
|
735
|
+
end
|
736
|
+
end
|
737
|
+
|
738
|
+
def info_format_unknown(packages)
|
739
|
+
packages.each_with_index do |package, index|
|
740
|
+
@out.puts if index != 0
|
741
|
+
|
742
|
+
package_records(package.name).each do |record|
|
743
|
+
path = record.restpath
|
744
|
+
@out.puts path if PlangDetector.new(path).unknown?
|
745
|
+
end
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
749
|
+
def package_records(name)
|
750
|
+
@documents.search(:strict_packages => [name])
|
751
|
+
end
|
752
|
+
|
753
|
+
def linecount_total(records)
|
754
|
+
records.reduce(0) do |total, record|
|
755
|
+
begin
|
756
|
+
unless record.content.nil?
|
757
|
+
total + record.content.count($/) + 1
|
758
|
+
else
|
759
|
+
total
|
760
|
+
end
|
761
|
+
rescue ArgumentError
|
762
|
+
warning_alert("invalid byte sequence : #{record.path}")
|
763
|
+
total
|
764
|
+
end
|
765
|
+
end
|
766
|
+
end
|
767
|
+
|
768
|
+
def sorted_plangs(records)
|
769
|
+
total = {}
|
770
|
+
|
771
|
+
records.each do |record|
|
772
|
+
lang = PlangDetector.new(record.restpath)
|
773
|
+
|
774
|
+
if total[lang.name]
|
775
|
+
total[lang.name] += 1
|
776
|
+
else
|
777
|
+
total[lang.name] = 1
|
778
|
+
end
|
779
|
+
end
|
780
|
+
|
781
|
+
total.map {|name, count|
|
782
|
+
[name, count]
|
783
|
+
}.sort {|a, b|
|
784
|
+
if (a[0] == PlangDetector::UNKNOWN)
|
785
|
+
-1
|
786
|
+
elsif (b[0] == PlangDetector::UNKNOWN)
|
787
|
+
1
|
788
|
+
else
|
789
|
+
a[1] <=> b[1]
|
790
|
+
end
|
791
|
+
}.reverse
|
792
|
+
end
|
793
|
+
|
794
|
+
def calc_percent(count, size)
|
795
|
+
(count.to_f / size * 100).to_i
|
796
|
+
end
|
797
|
+
|
798
|
+
def breakdown_shorten(records)
|
799
|
+
plangs = sorted_plangs(records)
|
800
|
+
|
801
|
+
plangs = plangs.reduce([]) {|array, plang|
|
802
|
+
name, count = plang
|
803
|
+
percent = calc_percent(count, records.size)
|
804
|
+
|
805
|
+
if percent == 0
|
806
|
+
if array.empty? || array[-1][0] != 'other'
|
807
|
+
array << ['other', count]
|
808
|
+
else
|
809
|
+
array[-1][1] += count
|
810
|
+
end
|
811
|
+
else
|
812
|
+
array << plang
|
813
|
+
end
|
814
|
+
|
815
|
+
array
|
816
|
+
}
|
817
|
+
|
818
|
+
plangs.map {|name, count|
|
819
|
+
percent = calc_percent(count, records.size)
|
820
|
+
"#{name}:#{count}(#{percent}%)"
|
821
|
+
}.join(', ')
|
822
|
+
end
|
823
|
+
|
824
|
+
def breakdown_detail(records, name_width)
|
825
|
+
sorted_plangs(records).map {|name, count|
|
826
|
+
percent = (count.to_f / records.size * 100).to_i
|
827
|
+
sprintf("%-#{name_width}s %5d %3d%%", name, count, percent)
|
828
|
+
}.join("\n")
|
829
|
+
end
|
830
|
+
|
831
|
+
# 引数が指定されている時は名前にマッチするパッケージを、未指定の時は現在位置から見つける
|
832
|
+
def find_packages(args)
|
833
|
+
unless args.empty?
|
834
|
+
args.map do |v|
|
835
|
+
r = @yaml.find_name(v)
|
836
|
+
@out.puts "Not found package '#{v}'." if r.nil?
|
837
|
+
r
|
838
|
+
end
|
839
|
+
else
|
840
|
+
dir = File.expand_path('.')
|
841
|
+
r = @yaml.package_root(dir)
|
842
|
+
@out.puts "Not registered '#{dir}'." if r.nil?
|
843
|
+
[r]
|
844
|
+
end
|
643
845
|
end
|
644
846
|
|
645
847
|
def ignore(args, options)
|
@@ -697,6 +899,19 @@ EOF
|
|
697
899
|
end
|
698
900
|
end
|
699
901
|
|
902
|
+
def files(args)
|
903
|
+
packages = find_packages(args)
|
904
|
+
return if (packages.empty?)
|
905
|
+
|
906
|
+
db_open
|
907
|
+
|
908
|
+
packages.each do |package|
|
909
|
+
package_records(package.name).each do |record|
|
910
|
+
@out.puts record.restpath
|
911
|
+
end
|
912
|
+
end
|
913
|
+
end
|
914
|
+
|
700
915
|
private
|
701
916
|
|
702
917
|
def db_file
|
@@ -712,37 +927,38 @@ EOF
|
|
712
927
|
end
|
713
928
|
|
714
929
|
def update_package_in(package, options)
|
715
|
-
|
716
|
-
Dir.chdir(package.directory) { system("git pull") }
|
717
|
-
end
|
718
|
-
|
719
|
-
unless options[:no_clean]
|
720
|
-
cleanup_package_in(package)
|
721
|
-
end
|
722
|
-
|
723
|
-
update_dir_in(package.directory)
|
724
|
-
end
|
725
|
-
|
726
|
-
def cleanup_package_in(package)
|
727
|
-
db_open
|
728
|
-
@documents.cleanup_package_name(package.name)
|
930
|
+
updater_exec(package, package.options[:update_with_git_pull], options[:no_clean])
|
729
931
|
end
|
730
932
|
|
731
933
|
def update_dir_in(dir)
|
732
|
-
alert("package", File.basename(dir) )
|
733
|
-
@package_count += 1
|
734
|
-
|
735
934
|
dir = File.expand_path(dir)
|
736
935
|
|
737
936
|
if (!FileTest.exist?(dir))
|
738
|
-
|
739
|
-
elsif (FileTest.directory? dir)
|
740
|
-
db_add_dir(dir)
|
937
|
+
warning_alert("#{dir} (Not found, skip)")
|
741
938
|
else
|
742
|
-
|
939
|
+
package = @yaml.package_root(dir)
|
940
|
+
updater_exec(package, false, false)
|
743
941
|
end
|
744
942
|
end
|
745
943
|
|
944
|
+
def updater_exec(package, is_update_with_git_pull, is_no_clean)
|
945
|
+
alert("package", package.name )
|
946
|
+
|
947
|
+
updater = Updater.new(@grndb, package.name)
|
948
|
+
updater.set_package_ignore IgnoreSetting.new("/", package.ignore)
|
949
|
+
updater.enable_no_auto_ignore if package.options[:no_auto_ignore]
|
950
|
+
updater.enable_silent_mode if @is_silent
|
951
|
+
updater.enable_display_info if @is_display_info
|
952
|
+
updater.enable_update_with_git_pull if is_update_with_git_pull
|
953
|
+
updater.enable_no_clean if is_no_clean
|
954
|
+
updater.exec
|
955
|
+
|
956
|
+
@package_count += 1
|
957
|
+
@file_count += updater.result.file_count
|
958
|
+
@add_count += updater.result.add_count
|
959
|
+
@update_count += updater.result.update_count
|
960
|
+
end
|
961
|
+
|
746
962
|
def remove_dir(dir, no_yaml = false)
|
747
963
|
unless (no_yaml)
|
748
964
|
package = @yaml.find_dir(dir)
|
@@ -790,7 +1006,6 @@ EOF
|
|
790
1006
|
r << "#{@file_count} records" if @file_count > 0
|
791
1007
|
r << "#{@add_count} add" if @add_count > 0
|
792
1008
|
r << "#{@update_count} update" if @update_count > 0
|
793
|
-
r.join(', ')
|
794
1009
|
alert('result', "#{r.join(', ')}. (#{Gren::Util::time_s(time)})")
|
795
1010
|
end
|
796
1011
|
|
@@ -835,108 +1050,6 @@ EOF
|
|
835
1050
|
end
|
836
1051
|
end
|
837
1052
|
|
838
|
-
def db_add_dir(dir)
|
839
|
-
@current_package = @yaml.package_root(dir)
|
840
|
-
@current_ignore = IgnoreChecker.new
|
841
|
-
@current_ignore.add IgnoreSetting.new("/", @current_package.ignore) # 手動設定
|
842
|
-
searchDirectory(STDOUT, dir, @current_package.name, "/", 0)
|
843
|
-
end
|
844
|
-
private :db_add_dir
|
845
|
-
|
846
|
-
def db_add_file(stdout, package_dir, restpath, package_name = nil)
|
847
|
-
# サイレントモード
|
848
|
-
return if @is_silent
|
849
|
-
|
850
|
-
# データベースには先頭の'/'を抜いて登録する
|
851
|
-
# 最初から'/'を抜いておけば高速化の余地あり?
|
852
|
-
# ignore設定との互換性保持が必要
|
853
|
-
restpath = restpath.sub(/^\//, "")
|
854
|
-
|
855
|
-
# パッケージ名を設定
|
856
|
-
package_name = package_name || File.basename(package_dir)
|
857
|
-
|
858
|
-
# レコードの追加
|
859
|
-
result = @documents.add(package_dir, restpath, package_name)
|
860
|
-
|
861
|
-
# メッセージの表示
|
862
|
-
case result
|
863
|
-
when :newfile
|
864
|
-
@add_count += 1
|
865
|
-
alert_info("add_record", File.join(package_dir, restpath))
|
866
|
-
when :update
|
867
|
-
@grndb.packages.touch(package_name, :updatetime)
|
868
|
-
@update_count += 1
|
869
|
-
alert_info("update", File.join(package_dir, restpath))
|
870
|
-
end
|
871
|
-
end
|
872
|
-
|
873
|
-
def searchDirectory(stdout, dirname, packname, path, depth)
|
874
|
-
# 現在位置に.gitignoreがあれば無視設定に加える
|
875
|
-
add_current_gitignore(dirname, path) unless @current_package.options[:no_auto_ignore]
|
876
|
-
|
877
|
-
# 子の要素を追加
|
878
|
-
Dir.foreach(File.join(dirname, path)) do |name|
|
879
|
-
next if (name == '.' || name == '..')
|
880
|
-
|
881
|
-
next_path = File.join(path, name)
|
882
|
-
fpath = File.join(dirname, next_path)
|
883
|
-
shortpath = File.join(packname, next_path)
|
884
|
-
|
885
|
-
# 除外ディレクトリならばパス
|
886
|
-
next if ignoreDir?(fpath, next_path)
|
887
|
-
|
888
|
-
# 読み込み不可ならばパス
|
889
|
-
next unless FileTest.readable?(fpath)
|
890
|
-
|
891
|
-
# ファイルならば中身を探索、ディレクトリならば再帰
|
892
|
-
case File.ftype(fpath)
|
893
|
-
when "directory"
|
894
|
-
searchDirectory(stdout, dirname, packname, next_path, depth + 1)
|
895
|
-
when "file"
|
896
|
-
unless ignoreFile?(fpath, next_path)
|
897
|
-
db_add_file(stdout, dirname, next_path) # shortpathの先頭に'/'が付いているのが気になる
|
898
|
-
@file_count += 1
|
899
|
-
# @out.puts "file_count : #{@file_count}" if (@file_count % 100 == 0)
|
900
|
-
end
|
901
|
-
end
|
902
|
-
end
|
903
|
-
end
|
904
|
-
|
905
|
-
def add_current_gitignore(dirname, path)
|
906
|
-
git_ignore = File.join(dirname, path, ".gitignore")
|
907
|
-
|
908
|
-
if File.exist? git_ignore
|
909
|
-
alert_info("add_ignore", git_ignore)
|
910
|
-
|
911
|
-
open(git_ignore) do |f|
|
912
|
-
@current_ignore.add IgnoreSetting.create_from_gitignore(path, f.read)
|
913
|
-
end
|
914
|
-
end
|
915
|
-
end
|
916
|
-
|
917
|
-
def package_ignore?(fpath, mini_path)
|
918
|
-
if @current_ignore.ignore?(mini_path)
|
919
|
-
alert_info("ignore", fpath)
|
920
|
-
true
|
921
|
-
else
|
922
|
-
false
|
923
|
-
end
|
924
|
-
end
|
925
|
-
|
926
|
-
def ignoreDir?(fpath, mini_path)
|
927
|
-
FileTest.directory?(fpath) &&
|
928
|
-
(GrenFileTest::ignoreDir?(fpath) ||
|
929
|
-
package_ignore?(fpath, mini_path))
|
930
|
-
end
|
931
|
-
private :ignoreDir?
|
932
|
-
|
933
|
-
def ignoreFile?(fpath, mini_path)
|
934
|
-
GrenFileTest::ignoreFile?(fpath) ||
|
935
|
-
GrenFileTest::binary?(fpath) ||
|
936
|
-
package_ignore?(fpath, mini_path)
|
937
|
-
end
|
938
|
-
private :ignoreFile?
|
939
|
-
|
940
1053
|
def alert(title, msg)
|
941
1054
|
if (Util::platform_win?)
|
942
1055
|
@out.puts "#{title.ljust(10)} : #{Kconv.kconv(msg, Kconv::SJIS)}"
|