milkode 0.9.2 → 0.9.3
Sign up to get free protection for your applications and to get access to all the features.
- 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)}"
|