milkode 0.9.2 → 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -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.2
1
+ 0.9.3
data/bin/gmilk CHANGED
@@ -6,5 +6,5 @@
6
6
  require 'rubygems'
7
7
  require 'milkode/grep/cli_grep'
8
8
 
9
- Version = "0.9.2"
9
+ Version = "0.9.3"
10
10
  Milkode::CLI_Grep.execute(STDOUT, ARGV)
data/bin/milk CHANGED
@@ -6,5 +6,5 @@
6
6
  require 'rubygems'
7
7
  require 'milkode/cli'
8
8
 
9
- Version = "0.9.2"
9
+ Version = "0.9.3"
10
10
  Milkode::CLI.start(ARGV)
@@ -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
- # print information
390
- if args.empty?
391
- milkode_info
392
- else
393
- list_info(match_p) unless match_p.empty?
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
- milkode_info
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
- if package.options[:update_with_git_pull]
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
- @out.puts "[WARNING] : #{dir} (Not found, skip)"
739
- elsif (FileTest.directory? dir)
740
- db_add_dir(dir)
937
+ warning_alert("#{dir} (Not found, skip)")
741
938
  else
742
- db_add_file(STDOUT, File.dirname(dir), File.basename(dir), File.basename(dir)) # .bashrc/.bashrc のようになる
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)}"