| 
									
										
										
										
											2020-10-10 14:16:11 +02:00
										 |  |  | # typed: false | 
					
						
							| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-04-17 18:25:08 +09:00
										 |  |  | require_relative "../../cli/parser" | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  | describe Homebrew::CLI::Parser do | 
					
						
							|  |  |  |   describe "test switch options" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							| 
									
										
										
										
											2018-03-29 03:20:14 +05:30
										 |  |  |         switch "--more-verbose", description: "Flag for higher verbosity" | 
					
						
							| 
									
										
										
										
											2018-03-25 11:04:18 +05:30
										 |  |  |         switch "--pry", env: :pry | 
					
						
							| 
									
										
										
										
											2021-06-08 22:02:32 -04:00
										 |  |  |         switch "--hidden", hidden: true | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-20 09:07:56 +01:00
										 |  |  |     before do | 
					
						
							| 
									
										
										
										
											2020-04-05 15:44:50 +01:00
										 |  |  |       allow(Homebrew::EnvConfig).to receive(:pry?).and_return(true) | 
					
						
							| 
									
										
										
										
											2018-09-20 09:07:56 +01:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 20:03:15 +02:00
										 |  |  |     context "when using binary options" do | 
					
						
							| 
									
										
										
										
											2020-08-01 02:30:46 +02:00
										 |  |  |       subject(:parser) { | 
					
						
							|  |  |  |         described_class.new do | 
					
						
							|  |  |  |           switch "--[no-]positive" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       it "does not create no_positive?" do | 
					
						
							|  |  |  |         args = parser.parse(["--no-positive"]) | 
					
						
							|  |  |  |         expect { args.no_positive? }.to raise_error(NoMethodError) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-01 02:30:46 +02:00
										 |  |  |       it "sets the positive name to false if the negative flag is passed" do | 
					
						
							|  |  |  |         args = parser.parse(["--no-positive"]) | 
					
						
							|  |  |  |         expect(args).not_to be_positive | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it "sets the positive name to true if the positive flag is passed" do | 
					
						
							|  |  |  |         args = parser.parse(["--positive"]) | 
					
						
							|  |  |  |         expect(args).to be_positive | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |       it "does not set the positive name if the positive flag is not passed" do | 
					
						
							|  |  |  |         args = parser.parse([]) | 
					
						
							|  |  |  |         expect(args.positive?).to be nil | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2020-08-01 02:30:46 +02:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-14 20:03:15 +02:00
										 |  |  |     context "when using negative options" do | 
					
						
							|  |  |  |       subject(:parser) { | 
					
						
							|  |  |  |         described_class.new do | 
					
						
							|  |  |  |           switch "--no-positive" | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it "does not set the positive name" do | 
					
						
							|  |  |  |         args = parser.parse(["--no-positive"]) | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |         expect { args.positive? }.to raise_error(NoMethodError) | 
					
						
							| 
									
										
										
										
											2020-08-14 20:03:15 +02:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it "fails when using the positive name" do | 
					
						
							|  |  |  |         expect { | 
					
						
							|  |  |  |           parser.parse(["--positive"]) | 
					
						
							|  |  |  |         }.to raise_error(/invalid option/) | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       it "sets the negative name to true if the negative flag is passed" do | 
					
						
							|  |  |  |         args = parser.parse(["--no-positive"]) | 
					
						
							|  |  |  |         expect(args.no_positive?).to be true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-07-31 15:07:08 +02:00
										 |  |  |     context "when `ignore_invalid_options` is true" do | 
					
						
							|  |  |  |       it "passes through invalid options" do | 
					
						
							|  |  |  |         args = parser.parse(["-v", "named-arg", "--not-a-valid-option"], ignore_invalid_options: true) | 
					
						
							|  |  |  |         expect(args.remaining).to eq ["named-arg", "--not-a-valid-option"] | 
					
						
							| 
									
										
										
										
											2020-11-16 01:52:57 +01:00
										 |  |  |         expect(args.named).to be_empty | 
					
						
							| 
									
										
										
										
											2020-07-31 15:07:08 +02:00
										 |  |  |       end | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     it "parses short option" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["-v"]) | 
					
						
							|  |  |  |       expect(args).to be_verbose | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a single valid option" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--verbose"]) | 
					
						
							|  |  |  |       expect(args).to be_verbose | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a valid option along with few unnamed args" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(%w[--verbose unnamed args]) | 
					
						
							|  |  |  |       expect(args).to be_verbose | 
					
						
							|  |  |  |       expect(args.named).to eq %w[unnamed args] | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |     it "parses a single option and checks other options to be false" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--verbose"]) | 
					
						
							|  |  |  |       expect(args).to be_verbose | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       expect(args.more_verbose?).to be false | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 22:02:32 -04:00
										 |  |  |     it "sets the correct value for a hidden switch" do | 
					
						
							|  |  |  |       args = parser.parse([]) | 
					
						
							|  |  |  |       expect(args.hidden?).to be false | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-12 19:17:07 +00:00
										 |  |  |     it "raises an exception and outputs help text when an invalid option is passed" do | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |       expect { parser.parse(["--random"]) }.to raise_error(OptionParser::InvalidOption, /--random/) | 
					
						
							| 
									
										
										
										
											2019-01-12 19:17:07 +00:00
										 |  |  |                                            .and output(/Usage: brew/).to_stderr | 
					
						
							| 
									
										
										
										
											2019-01-12 18:52:07 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-25 11:04:18 +05:30
										 |  |  |     it "maps environment var to an option" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse([]) | 
					
						
							|  |  |  |       expect(args.pry?).to be true | 
					
						
							| 
									
										
										
										
											2018-10-24 17:10:13 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   describe "test long flag options" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							| 
									
										
										
										
											2018-04-14 19:04:24 +05:30
										 |  |  |         flag        "--filename=", description: "Name of the file" | 
					
						
							|  |  |  |         comma_array "--files",     description: "Comma separated filenames" | 
					
						
							| 
									
										
										
										
											2021-06-08 22:02:32 -04:00
										 |  |  |         flag        "--hidden=",      hidden: true | 
					
						
							|  |  |  |         comma_array "--hidden-array", hidden: true | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-25 13:30:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     it "parses a long flag option with its argument" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--filename=random.txt"]) | 
					
						
							|  |  |  |       expect(args.filename).to eq "random.txt" | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-04-14 19:04:24 +05:30
										 |  |  |     it "raises an exception when a flag's required value is not passed" do | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |       expect { parser.parse(["--filename"]) }.to raise_error(OptionParser::MissingArgument, /--filename/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a comma array flag option" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--files=random1.txt,random2.txt"]) | 
					
						
							|  |  |  |       expect(args.files).to eq %w[random1.txt random2.txt] | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-06-08 22:02:32 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it "sets the correct value for hidden flags" do | 
					
						
							|  |  |  |       args = parser.parse(["--hidden=foo", "--hidden-array=bar,baz"]) | 
					
						
							|  |  |  |       expect(args.hidden).to eq "foo" | 
					
						
							|  |  |  |       expect(args.hidden_array).to eq %w[bar baz] | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-25 21:43:49 +05:30
										 |  |  |   describe "test short flag options" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         flag "-f", "--filename=", description: "Name of the file" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a short flag option with its argument" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--filename=random.txt"]) | 
					
						
							|  |  |  |       expect(args.filename).to eq "random.txt" | 
					
						
							|  |  |  |       expect(args.f).to eq "random.txt" | 
					
						
							| 
									
										
										
										
											2018-10-25 21:43:49 +05:30
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |   describe "test constraints for flag options" do | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |         flag      "--flag1=" | 
					
						
							|  |  |  |         flag      "--flag3=" | 
					
						
							|  |  |  |         flag      "--flag2=", required_for: "--flag1=" | 
					
						
							|  |  |  |         flag      "--flag4=", depends_on: "--flag3=" | 
					
						
							| 
									
										
										
										
											2018-04-14 16:17:14 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |         conflicts "--flag1=", "--flag3=" | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |     it "raises exception on required_for constraint violation" do | 
					
						
							|  |  |  |       expect { parser.parse(["--flag1=flag1"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |     it "raises exception on depends_on constraint violation" do | 
					
						
							|  |  |  |       expect { parser.parse(["--flag2=flag2"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							| 
									
										
										
										
											2018-10-06 22:52:47 -04:00
										 |  |  |       expect { parser.parse(["--flag4=flag4"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises exception for conflict violation" do | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |       expect { parser.parse(["--flag1=flag1", "--flag3=flag3"]) }.to raise_error(Homebrew::CLI::OptionConflictError) | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises no exception" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--flag1=flag1", "--flag2=flag2"]) | 
					
						
							|  |  |  |       expect(args.flag1).to eq "flag1" | 
					
						
							|  |  |  |       expect(args.flag2).to eq "flag2" | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises no exception for optional dependency" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--flag3=flag3"]) | 
					
						
							|  |  |  |       expect(args.flag3).to eq "flag3" | 
					
						
							| 
									
										
										
										
											2018-04-01 22:01:06 +05:30
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-04-14 16:17:14 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   describe "test invalid constraints" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |         flag      "--flag1=" | 
					
						
							|  |  |  |         flag      "--flag2=", depends_on: "--flag1=" | 
					
						
							|  |  |  |         conflicts "--flag1=", "--flag2=" | 
					
						
							| 
									
										
										
										
											2018-04-14 16:17:14 +05:30
										 |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises exception due to invalid constraints" do | 
					
						
							|  |  |  |       expect { parser.parse([]) }.to raise_error(Homebrew::CLI::InvalidConstraintError) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   describe "test constraints for switch options" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							| 
									
										
										
										
											2019-02-15 00:31:13 -05:00
										 |  |  |         switch      "-a", "--switch-a", env: "switch_a" | 
					
						
							|  |  |  |         switch      "-b", "--switch-b", env: "switch_b" | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |         switch      "--switch-c", required_for: "--switch-a" | 
					
						
							|  |  |  |         switch      "--switch-d", depends_on: "--switch-b" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         conflicts "--switch-a", "--switch-b" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises exception on required_for constraint violation" do | 
					
						
							|  |  |  |       expect { parser.parse(["--switch-a"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises exception on depends_on constraint violation" do | 
					
						
							|  |  |  |       expect { parser.parse(["--switch-c"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							| 
									
										
										
										
											2018-10-06 22:52:47 -04:00
										 |  |  |       expect { parser.parse(["--switch-d"]) }.to raise_error(Homebrew::CLI::OptionConstraintError) | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises exception for conflict violation" do | 
					
						
							|  |  |  |       expect { parser.parse(["-ab"]) }.to raise_error(Homebrew::CLI::OptionConflictError) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises no exception" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--switch-a", "--switch-c"]) | 
					
						
							|  |  |  |       expect(args.switch_a?).to be true | 
					
						
							|  |  |  |       expect(args.switch_c?).to be true | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises no exception for optional dependency" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--switch-b"]) | 
					
						
							|  |  |  |       expect(args.switch_b?).to be true | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2019-02-15 00:31:13 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it "prioritizes cli arguments over env vars when they conflict" do | 
					
						
							| 
									
										
										
										
											2020-04-05 15:44:50 +01:00
										 |  |  |       allow(Homebrew::EnvConfig).to receive(:switch_a?).and_return(true) | 
					
						
							|  |  |  |       allow(Homebrew::EnvConfig).to receive(:switch_b?).and_return(false) | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--switch-b"]) | 
					
						
							| 
									
										
										
										
											2021-03-18 14:46:48 +00:00
										 |  |  |       expect(args.switch_a?).to be false | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       expect(args).to be_switch_b | 
					
						
							| 
									
										
										
										
											2019-02-15 00:31:13 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises an exception on constraint violation when both are env vars" do | 
					
						
							| 
									
										
										
										
											2020-04-05 15:44:50 +01:00
										 |  |  |       allow(Homebrew::EnvConfig).to receive(:switch_a?).and_return(true) | 
					
						
							|  |  |  |       allow(Homebrew::EnvConfig).to receive(:switch_b?).and_return(true) | 
					
						
							| 
									
										
										
										
											2019-02-25 14:54:31 -05:00
										 |  |  |       expect { parser.parse([]) }.to raise_error(Homebrew::CLI::OptionConflictError) | 
					
						
							| 
									
										
										
										
											2019-02-15 00:31:13 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2018-05-25 04:05:45 +05:30
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-10-29 02:27:00 +05:30
										 |  |  | 
 | 
					
						
							|  |  |  |   describe "test immutability of args" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         switch "-a", "--switch-a" | 
					
						
							|  |  |  |         switch "-b", "--switch-b" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-23 03:43:54 +02:00
										 |  |  |     it "raises exception when arguments were already parsed" do | 
					
						
							| 
									
										
										
										
											2018-10-29 02:27:00 +05:30
										 |  |  |       parser.parse(["--switch-a"]) | 
					
						
							| 
									
										
										
										
											2019-04-17 19:43:06 +09:00
										 |  |  |       expect { parser.parse(["--switch-b"]) }.to raise_error(RuntimeError, /Arguments were already parsed!/) | 
					
						
							| 
									
										
										
										
											2018-10-29 02:27:00 +05:30
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-25 15:57:09 -05:00
										 |  |  |   describe "test inferrability of args" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         switch "--switch-a" | 
					
						
							|  |  |  |         switch "--switch-b" | 
					
						
							|  |  |  |         switch "--foo-switch" | 
					
						
							|  |  |  |         flag "--flag-foo=" | 
					
						
							|  |  |  |         comma_array "--comma-array-foo" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a valid switch that uses `_` instead of `-`" do | 
					
						
							|  |  |  |       args = parser.parse(["--switch_a"]) | 
					
						
							|  |  |  |       expect(args).to be_switch_a | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a valid flag that uses `_` instead of `-`" do | 
					
						
							|  |  |  |       args = parser.parse(["--flag_foo=foo.txt"]) | 
					
						
							|  |  |  |       expect(args.flag_foo).to eq "foo.txt" | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "parses a valid comma_array that uses `_` instead of `-`" do | 
					
						
							|  |  |  |       args = parser.parse(["--comma_array_foo=foo.txt,bar.txt"]) | 
					
						
							|  |  |  |       expect(args.comma_array_foo).to eq %w[foo.txt bar.txt] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "raises an error when option is ambiguous" do | 
					
						
							|  |  |  |       expect { parser.parse(["--switch"]) }.to raise_error(RuntimeError, /ambiguous option: --switch/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "inferrs the option from an abbreviated name" do | 
					
						
							|  |  |  |       args = parser.parse(["--foo"]) | 
					
						
							|  |  |  |       expect(args).to be_foo_switch | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  |   describe "test argv extensions" do | 
					
						
							|  |  |  |     subject(:parser) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         switch "--foo" | 
					
						
							|  |  |  |         flag   "--bar" | 
					
						
							|  |  |  |         switch "-s" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "#options_only" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--foo", "--bar=value", "-v", "-s", "a", "b", "cdefg"]) | 
					
						
							|  |  |  |       expect(args.options_only).to eq %w[--verbose --foo --bar=value -s] | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "#flags_only" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["--foo", "--bar=value", "-v", "-s", "a", "b", "cdefg"]) | 
					
						
							|  |  |  |       expect(args.flags_only).to eq %w[--verbose --foo --bar=value] | 
					
						
							| 
									
										
										
										
											2019-09-25 14:21:06 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2019-10-20 21:00:05 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 19:56:24 +05:30
										 |  |  |     it "#named returns an array of non-option arguments" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse(["foo", "-v", "-s"]) | 
					
						
							|  |  |  |       expect(args.named).to eq ["foo"] | 
					
						
							| 
									
										
										
										
											2019-09-08 19:56:24 +05:30
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "#named returns an empty array when there are no named arguments" do | 
					
						
							| 
									
										
										
										
											2020-07-30 18:40:10 +02:00
										 |  |  |       args = parser.parse([]) | 
					
						
							|  |  |  |       expect(args.named).to be_empty | 
					
						
							| 
									
										
										
										
											2019-09-08 19:56:24 +05:30
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2019-09-22 20:13:11 +05:30
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |   describe "usage banner generation" do | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |     it "includes `[options]` if more than two non-global options are available" do | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         switch "--foo" | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |         switch "--baz" | 
					
						
							|  |  |  |         switch "--bar" | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/\[options\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |     it "includes individual options if less than two non-global options are available" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         switch "--foo" | 
					
						
							|  |  |  |         switch "--bar" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/\[--foo\] \[--bar\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "formats flags correctly when less than two non-global options are available" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         flag "--foo" | 
					
						
							|  |  |  |         flag "--bar=" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/\[--foo\] \[--bar=\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "formats comma arrays correctly when less than two non-global options are available" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         comma_array "--foo" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/\[--foo=\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-08 22:02:32 -04:00
										 |  |  |     it "does not include hidden options" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         switch "--foo", hidden: true | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).not_to match(/\[--foo\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |     it "doesn't include `[options]` if non non-global options are available" do | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |       parser = described_class.new | 
					
						
							|  |  |  |       expect(parser.generate_help_text).not_to match(/\[options\]/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "includes a description" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         description <<~EOS | 
					
						
							|  |  |  |           This command does something | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/This command does something/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 11:20:01 +10:00
										 |  |  |     it "allows the usage banner to be overridden" do | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         usage_banner "`test` [foo] <bar>" | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/test \[foo\] bar/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-08 11:20:01 +10:00
										 |  |  |     it "allows a usage banner and a description to be overridden" do | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         usage_banner "`test` [foo] <bar>" | 
					
						
							|  |  |  |         description <<~EOS | 
					
						
							|  |  |  |           This command does something | 
					
						
							|  |  |  |         EOS | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/test \[foo\] bar/) | 
					
						
							|  |  |  |       expect(parser.generate_help_text).to match(/This command does something/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for no named argument" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :none | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: [^\[]+$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for a single typed argument" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :formula, number: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: .* formula$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for a subcommand argument with a maximum" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args %w[off on], max: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: .* \[subcommand\]$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for multiple typed argument with no maximum or minimum" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args [:tap, :command] | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: .* \[tap|command ...\]$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for a subcommand argument with a minimum of 1" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :installed_formula, min: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: .* installed_formula \[...\]$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "shows the correct usage for a subcommand argument with a minimum greater than 1" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :installed_formula, min: 2
 | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-18 11:28:45 -05:00
										 |  |  |       expect(parser.generate_help_text).to match(/^Usage: .* installed_formula ...$/s) | 
					
						
							| 
									
										
										
										
											2021-01-15 14:47:51 -05:00
										 |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |   describe "named_args" do | 
					
						
							|  |  |  |     let(:parser_none) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         named_args :none | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     let(:parser_number) { | 
					
						
							|  |  |  |       described_class.new do | 
					
						
							|  |  |  |         named_args number: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't allow :none passed with a number" do | 
					
						
							|  |  |  |       expect do | 
					
						
							|  |  |  |         described_class.new do | 
					
						
							|  |  |  |           named_args :none, number: 1
 | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end.to raise_error(ArgumentError, /Do not specify both `number`, `min` or `max` with `named_args :none`/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't allow number and min" do | 
					
						
							|  |  |  |       expect do | 
					
						
							|  |  |  |         described_class.new do | 
					
						
							|  |  |  |           named_args number: 1, min: 1
 | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  |       end.to raise_error(ArgumentError, /Do not specify both `number` and `min` or `max`/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't accept fewer than the passed number of arguments" do | 
					
						
							| 
									
										
										
										
											2021-01-23 15:25:56 -05:00
										 |  |  |       expect { parser_number.parse([]) }.to raise_error(Homebrew::CLI::NumberOfNamedArgumentsError) | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't accept more than the passed number of arguments" do | 
					
						
							| 
									
										
										
										
											2021-01-23 15:25:56 -05:00
										 |  |  |       expect { parser_number.parse(["foo", "bar"]) }.to raise_error(Homebrew::CLI::NumberOfNamedArgumentsError) | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "accepts the passed number of arguments" do | 
					
						
							|  |  |  |       expect { parser_number.parse(["foo"]) }.not_to raise_error | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't accept any arguments with :none" do | 
					
						
							|  |  |  |       expect { parser_none.parse(["foo"]) } | 
					
						
							|  |  |  |         .to raise_error(Homebrew::CLI::MaxNamedArgumentsError, /This command does not take named arguments/) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "accepts no arguments with :none" do | 
					
						
							|  |  |  |       expect { parser_none.parse([]) }.not_to raise_error | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |     it "displays the correct error message with no arg types and min" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args min: 2
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse([]) }.to raise_error( | 
					
						
							|  |  |  |         Homebrew::CLI::MinNamedArgumentsError, /This command requires at least 2 named arguments/ | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "displays the correct error message with no arg types and number" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args number: 2
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse([]) }.to raise_error( | 
					
						
							| 
									
										
										
										
											2021-01-23 15:25:56 -05:00
										 |  |  |         Homebrew::CLI::NumberOfNamedArgumentsError, /This command requires exactly 2 named arguments/ | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |       ) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "displays the correct error message with no arg types and max" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args max: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse(%w[foo bar]) }.to raise_error( | 
					
						
							|  |  |  |         Homebrew::CLI::MaxNamedArgumentsError, /This command does not take more than 1 named argument/ | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |     it "displays the correct error message with an array of strings" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |         named_args %w[on off], number: 1
 | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |       expect { parser.parse([]) }.to raise_error( | 
					
						
							| 
									
										
										
										
											2021-01-23 15:25:56 -05:00
										 |  |  |         Homebrew::CLI::NumberOfNamedArgumentsError, /This command requires exactly 1 subcommand/ | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "displays the correct error message with an array of symbols" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args [:formula, :cask], min: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							| 
									
										
										
										
											2021-01-23 15:06:44 -05:00
										 |  |  |       expect { parser.parse([]) }.to raise_error( | 
					
						
							|  |  |  |         Homebrew::CLI::MinNamedArgumentsError, /This command requires at least 1 formula or cask argument/ | 
					
						
							|  |  |  |       ) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "displays the correct error message with an array of symbols and max" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args [:formula, :cask], max: 1
 | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse(%w[foo bar]) }.to raise_error( | 
					
						
							|  |  |  |         Homebrew::CLI::MaxNamedArgumentsError, /This command does not take more than 1 formula or cask argument/ | 
					
						
							|  |  |  |       ) | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-08-25 14:34:57 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  |     it "accepts commands with :command" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :command | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse(["--prefix", "--version"]) }.not_to raise_error | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     it "doesn't accept invalid options with :command" do | 
					
						
							|  |  |  |       parser = described_class.new do | 
					
						
							|  |  |  |         named_args :command | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       expect { parser.parse(["--not-a-command"]) }.to raise_error(OptionParser::InvalidOption, /--not-a-command/) | 
					
						
							|  |  |  |     end | 
					
						
							| 
									
										
										
										
											2021-01-14 15:14:10 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2018-02-04 22:09:35 +05:30
										 |  |  | end |