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.
@@ -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)}"