##// END OF EJS Templates
rust-ignore: add some tests of `debugignorerhg`, add flag -a to control output...
Arseniy Alekseyev -
r53251:ff19ddb2 default
parent child Browse files
Show More
@@ -1,43 +1,58
1 1 use crate::error::CommandError;
2 use clap::Arg;
2 3 use hg::dirstate::status::StatusError;
3 4 use hg::filepatterns::RegexCompleteness;
4 5 use hg::matchers::get_ignore_matcher_pre;
5 6 use log::warn;
6 7
7 8 pub const HELP_TEXT: &str = "
8 9 Show effective hgignore patterns used by rhg.
9 10
10 11 This is a pure Rust version of `hg debugignore`.
11 12
12 13 Some options might be missing, check the list below.
13 14 ";
14 15
15 16 pub fn args() -> clap::Command {
16 clap::command!("debugignorerhg").about(HELP_TEXT)
17 clap::command!("debugignorerhg")
18 .arg(
19 Arg::new("all-patterns")
20 .help("include all patterns, including ones for exact file matches")
21 .short('a')
22 .action(clap::ArgAction::SetTrue)
23 .long("all-patterns"),
24 ).about(HELP_TEXT)
17 25 }
18 26
19 27 pub fn run(invocation: &crate::CliInvocation) -> Result<(), CommandError> {
20 28 let repo = invocation.repo?;
29 let args = invocation.subcommand_args;
21 30
22 31 let ignore_file = repo.working_directory_vfs().join(".hgignore"); // TODO hardcoded
32 let all_patterns = args.get_flag("all-patterns");
23 33
24 34 let (ignore_matcher, warnings) = get_ignore_matcher_pre(
25 35 vec![ignore_file],
26 36 repo.working_directory_path(),
27 37 &mut |_source, _pattern_bytes| (),
28 38 )
29 39 .map_err(StatusError::from)?;
30 40
41 let regex_config = if all_patterns {
42 RegexCompleteness::Complete
43 } else {
44 RegexCompleteness::ExcludeExactFiles
45 };
31 46 let ignore_matcher = ignore_matcher
32 .build_debug_matcher(RegexComprehensiveness::Comprehensive)
47 .build_debug_matcher(regex_config)
33 48 .map_err(StatusError::from)?;
34 49
35 50 if !warnings.is_empty() {
36 51 warn!("Pattern warnings: {:?}", &warnings);
37 52 }
38 53
39 54 let patterns = ignore_matcher.debug_get_patterns();
40 55 invocation.ui.write_stdout(patterns)?;
41 56 invocation.ui.write_stdout(b"\n")?;
42 57 Ok(())
43 58 }
@@ -1,546 +1,601
1 1 #testcases dirstate-v1 dirstate-v2
2 2
3 3 #if dirstate-v2
4 4 $ cat >> $HGRCPATH << EOF
5 5 > [format]
6 6 > use-dirstate-v2=1
7 7 > [storage]
8 8 > dirstate-v2.slow-path=allow
9 9 > EOF
10 10 #endif
11 11
12 12 $ hg init ignorerepo
13 13 $ cd ignorerepo
14 14
15 15 debugignore with no hgignore should be deterministic:
16 16 $ hg debugignore
17 17 <nevermatcher>
18 18
19 #if rhg
20 $ hg debugignorerhg
21
22 #endif
23
19 24 Issue562: .hgignore requires newline at end:
20 25
21 26 $ touch foo
22 27 $ touch bar
23 28 $ touch baz
24 29 $ cat > makeignore.py <<EOF
25 30 > f = open(".hgignore", "w")
26 31 > f.write("ignore\n")
27 32 > f.write("foo\n")
28 33 > # No EOL here
29 34 > f.write("bar")
30 35 > f.close()
31 36 > EOF
32 37
33 38 $ "$PYTHON" makeignore.py
34 39
35 40 Should display baz only:
36 41
37 42 $ hg status
38 43 ? baz
39 44
40 45 $ rm foo bar baz .hgignore makeignore.py
41 46
42 47 $ touch a.o
43 48 $ touch a.c
44 49 $ touch syntax
45 50 $ mkdir dir
46 51 $ touch dir/a.o
47 52 $ touch dir/b.o
48 53 $ touch dir/c.o
49 54
50 55 $ hg add dir/a.o
51 56 $ hg commit -m 0
52 57 $ hg add dir/b.o
53 58
54 59 $ hg status
55 60 A dir/b.o
56 61 ? a.c
57 62 ? a.o
58 63 ? dir/c.o
59 64 ? syntax
60 65
61 66 $ echo "*.o" > .hgignore
62 67 $ hg status
63 68 abort: $TESTTMP/ignorerepo/.hgignore: invalid pattern (relre): *.o (glob)
64 69 [255]
65 70
66 71 Test relre with flags (issue6759)
67 72 ---------------------------------
68 73
69 74 regexp with flag is the first one
70 75
71 76 $ echo 're:(?i)\.O$' > .hgignore
72 77 $ echo 're:.hgignore' >> .hgignore
73 78 $ hg status
74 79 A dir/b.o
75 80 ? a.c
76 81 ? syntax
77 82 $ hg debugignore
78 83 <includematcher includes='(?i:.*\\.O$)|.*.hgignore'>
79 84
85 #if rhg
86 $ hg debugignorerhg
87 (?i:.*\.O$)|.*.hgignore
88 #endif
89
80 90 regex with flag is not the first one
81 91
82 92 $ echo 're:.hgignore' > .hgignore
83 93 $ echo 're:(?i)\.O$' >> .hgignore
84 94 $ hg status
85 95 A dir/b.o
86 96 ? a.c
87 97 ? syntax
88 98 $ hg debugignore
89 99 <includematcher includes='.*.hgignore|(?i:.*\\.O$)'>
90 100
101 #if rhg
102 $ hg debugignorerhg
103 .*.hgignore|(?i:.*\.O$)
104 #endif
105
91 106 flag in a pattern should affect that pattern only
92 107
93 108 $ echo 're:(?i)\.O$' > .hgignore
94 109 $ echo 're:.HGIGNORE' >> .hgignore
95 110 $ hg status
96 111 A dir/b.o
97 112 ? .hgignore
98 113 ? a.c
99 114 ? syntax
100 115 $ hg debugignore
101 116 <includematcher includes='(?i:.*\\.O$)|.*.HGIGNORE'>
102 117
118 #if rhg
119 $ hg debugignorerhg
120 (?i:.*\.O$)|.*.HGIGNORE
121 #endif
122
103 123 $ echo 're:.HGIGNORE' > .hgignore
104 124 $ echo 're:(?i)\.O$' >> .hgignore
105 125 $ hg status
106 126 A dir/b.o
107 127 ? .hgignore
108 128 ? a.c
109 129 ? syntax
110 130 $ hg debugignore
111 131 <includematcher includes='.*.HGIGNORE|(?i:.*\\.O$)'>
112 132
133 #if rhg
134 $ hg debugignorerhg
135 .*.HGIGNORE|(?i:.*\.O$)
136 #endif
137
113 138 Check that '^' after flag is properly detected.
114 139
115 140 $ echo 're:(?i)^[^a].*\.O$' > .hgignore
116 141 $ echo 're:.HGIGNORE' >> .hgignore
117 142 $ hg status
118 143 A dir/b.o
119 144 ? .hgignore
120 145 ? a.c
121 146 ? a.o
122 147 ? syntax
123 148 $ hg debugignore
124 149 <includematcher includes='(?i:^[^a].*\\.O$)|.*.HGIGNORE'>
125 150
151 #if rhg
152 $ hg debugignorerhg
153 (?i:^[^a].*\.O$)|.*.HGIGNORE
154 #endif
155
126 156 $ echo 're:.HGIGNORE' > .hgignore
127 157 $ echo 're:(?i)^[^a].*\.O$' >> .hgignore
128 158 $ hg status
129 159 A dir/b.o
130 160 ? .hgignore
131 161 ? a.c
132 162 ? a.o
133 163 ? syntax
134 164 $ hg debugignore
135 165 <includematcher includes='.*.HGIGNORE|(?i:^[^a].*\\.O$)'>
136 166
167 #if rhg
168 $ hg debugignorerhg
169 .*.HGIGNORE|(?i:^[^a].*\.O$)
170 #endif
137 171
138 172 further testing
139 173 ---------------
140 174
141 175 $ echo 're:^(?!a).*\.o$' > .hgignore
142 176 $ hg status
143 177 A dir/b.o
144 178 ? .hgignore
145 179 ? a.c
146 180 ? a.o
147 181 ? syntax
148 182 #if rhg
149 183 $ hg status --config rhg.on-unsupported=abort
150 184 unsupported feature: Unsupported syntax regex parse error:
151 185 ^(?:^(?!a).*\.o$)
152 186 ^^^
153 187 error: look-around, including look-ahead and look-behind, is not supported
154 188 [252]
155 189 #endif
156 190
157 191 Ensure given files are relative to cwd
158 192
159 193 $ echo "dir/.*\.o" > .hgignore
160 194 $ hg status -i
161 195 I dir/c.o
162 196
163 197 $ hg debugignore dir/c.o dir/missing.o
164 198 dir/c.o is ignored
165 199 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: 'dir/.*\.o') (glob)
166 200 dir/missing.o is ignored
167 201 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: 'dir/.*\.o') (glob)
168 202 $ cd dir
169 203 $ hg debugignore c.o missing.o
170 204 c.o is ignored
171 205 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: 'dir/.*\.o') (glob)
172 206 missing.o is ignored
173 207 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: 'dir/.*\.o') (glob)
174 208
175 209 For icasefs, inexact matches also work, except for missing files
176 210
177 211 #if icasefs
178 212 $ hg debugignore c.O missing.O
179 213 c.o is ignored
180 214 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: 'dir/.*\.o') (glob)
181 215 missing.O is not ignored
182 216 #endif
183 217
184 218 $ cd ..
185 219
186 220 $ echo ".*\.o" > .hgignore
187 221 $ hg status
188 222 A dir/b.o
189 223 ? .hgignore
190 224 ? a.c
191 225 ? syntax
192 226
193 227 Ensure that comments work:
194 228
195 229 $ touch 'foo#bar' 'quux#' 'quu0#'
196 230 #if no-windows
197 231 $ touch 'baz\' 'baz\wat' 'ba0\#wat' 'ba1\\' 'ba1\\wat' 'quu0\'
198 232 #endif
199 233
200 234 $ cat <<'EOF' >> .hgignore
201 235 > # full-line comment
202 236 > # whitespace-only comment line
203 237 > syntax# pattern, no whitespace, then comment
204 238 > a.c # pattern, then whitespace, then comment
205 239 > baz\\# # (escaped) backslash, then comment
206 240 > ba0\\\#w # (escaped) backslash, escaped comment character, then comment
207 241 > ba1\\\\# # (escaped) backslashes, then comment
208 242 > foo\#b # escaped comment character
209 243 > quux\## escaped comment character at end of name
210 244 > EOF
211 245 $ hg status
212 246 A dir/b.o
213 247 ? .hgignore
214 248 ? quu0#
215 249 ? quu0\ (no-windows !)
216 250
217 251 $ cat <<'EOF' > .hgignore
218 252 > .*\.o
219 253 > syntax: glob
220 254 > syntax# pattern, no whitespace, then comment
221 255 > a.c # pattern, then whitespace, then comment
222 256 > baz\\#* # (escaped) backslash, then comment
223 257 > ba0\\\#w* # (escaped) backslash, escaped comment character, then comment
224 258 > ba1\\\\#* # (escaped) backslashes, then comment
225 259 > foo\#b* # escaped comment character
226 260 > quux\## escaped comment character at end of name
227 261 > quu0[\#]# escaped comment character inside [...]
228 262 > EOF
229 263 $ hg status
230 264 A dir/b.o
231 265 ? .hgignore
232 266 ? ba1\\wat (no-windows !)
233 267 ? baz\wat (no-windows !)
234 268 ? quu0\ (no-windows !)
235 269
236 270 $ rm 'foo#bar' 'quux#' 'quu0#'
237 271 #if no-windows
238 272 $ rm 'baz\' 'baz\wat' 'ba0\#wat' 'ba1\\' 'ba1\\wat' 'quu0\'
239 273 #endif
240 274
241 275 Check that '^\.' does not ignore the root directory:
242 276
243 277 $ echo "^\." > .hgignore
244 278 $ hg status
245 279 A dir/b.o
246 280 ? a.c
247 281 ? a.o
248 282 ? dir/c.o
249 283 ? syntax
250 284
251 285 Test that patterns from ui.ignore options are read:
252 286
253 287 $ echo > .hgignore
254 288 $ cat >> $HGRCPATH << EOF
255 289 > [ui]
256 290 > ignore.other = $TESTTMP/ignorerepo/.hg/testhgignore
257 291 > EOF
258 292 $ echo "glob:**.o" > .hg/testhgignore
259 293 $ hg status
260 294 A dir/b.o
261 295 ? .hgignore
262 296 ? a.c
263 297 ? syntax
264 298
265 299 empty out testhgignore
266 300 $ echo > .hg/testhgignore
267 301
268 302 Test relative ignore path (issue4473):
269 303
270 304 $ cat >> $HGRCPATH << EOF
271 305 > [ui]
272 306 > ignore.relative = .hg/testhgignorerel
273 307 > EOF
274 308 $ echo "glob:*.o" > .hg/testhgignorerel
275 309 $ cd dir
276 310 $ hg status
277 311 A dir/b.o
278 312 ? .hgignore
279 313 ? a.c
280 314 ? syntax
281 315 $ hg debugignore
282 316 <includematcher includes='.*\\.o(?:/|$)'>
283 317
284 318 $ cd ..
285 319 $ echo > .hg/testhgignorerel
286 320 $ echo "syntax: glob" > .hgignore
287 321 $ echo "re:.*\.o" >> .hgignore
288 322 $ hg status
289 323 A dir/b.o
290 324 ? .hgignore
291 325 ? a.c
292 326 ? syntax
293 327
294 328 $ echo "syntax: invalid" > .hgignore
295 329 $ hg status
296 330 $TESTTMP/ignorerepo/.hgignore: ignoring invalid syntax 'invalid'
297 331 A dir/b.o
298 332 ? .hgignore
299 333 ? a.c
300 334 ? a.o
301 335 ? dir/c.o
302 336 ? syntax
303 337
304 338 $ echo "syntax: glob" > .hgignore
305 339 $ echo "*.o" >> .hgignore
306 340 $ hg status
307 341 A dir/b.o
308 342 ? .hgignore
309 343 ? a.c
310 344 ? syntax
311 345
312 346 $ echo "relglob:syntax*" > .hgignore
313 347 $ hg status
314 348 A dir/b.o
315 349 ? .hgignore
316 350 ? a.c
317 351 ? a.o
318 352 ? dir/c.o
319 353
354 $ echo "rootglob:dir/b.o" > .hgignore
355 $ hg status
356 A dir/b.o
357 ? .hgignore
358 ? a.c
359 ? a.o
360 ? dir/c.o
361 ? syntax
362 #if rhg
363 $ hg debugignorerhg -a
364 dir/b\.o(?:/|$)
365
366 $ hg debugignorerhg
367
368 #endif
369
320 370 $ echo "relglob:*" > .hgignore
321 371 $ hg status
322 372 A dir/b.o
323 373
324 374 $ cd dir
325 375 $ hg status .
326 376 A b.o
327 377
328 378 $ hg debugignore
329 379 <includematcher includes='.*(?:/|$)'>
330 380
381 #if rhg
382 $ hg debugignorerhg
383 .*(?:/|$)
384 #endif
385
331 386 $ hg debugignore b.o
332 387 b.o is ignored
333 388 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 1: '*') (glob)
334 389
335 390 $ cd ..
336 391
337 392 Check patterns that match only the directory
338 393
339 394 "(fsmonitor !)" below assumes that fsmonitor is enabled with
340 395 "walk_on_invalidate = false" (default), which doesn't involve
341 396 re-walking whole repository at detection of .hgignore change.
342 397
343 398 $ echo "^dir\$" > .hgignore
344 399 $ hg status
345 400 A dir/b.o
346 401 ? .hgignore
347 402 ? a.c
348 403 ? a.o
349 404 ? dir/c.o (fsmonitor !)
350 405 ? syntax
351 406
352 407 Check recursive glob pattern matches no directories (dir/**/c.o matches dir/c.o)
353 408
354 409 $ echo "syntax: glob" > .hgignore
355 410 $ echo "dir/**/c.o" >> .hgignore
356 411 $ touch dir/c.o
357 412 $ mkdir dir/subdir
358 413 $ touch dir/subdir/c.o
359 414 $ hg status
360 415 A dir/b.o
361 416 ? .hgignore
362 417 ? a.c
363 418 ? a.o
364 419 ? syntax
365 420 $ hg debugignore a.c
366 421 a.c is not ignored
367 422 $ hg debugignore dir/c.o
368 423 dir/c.o is ignored
369 424 (ignore rule in $TESTTMP/ignorerepo/.hgignore, line 2: 'dir/**/c.o') (glob)
370 425
371 426 Check rooted globs
372 427
373 428 $ hg purge --all --config extensions.purge=
374 429 $ echo "syntax: rootglob" > .hgignore
375 430 $ echo "a/*.ext" >> .hgignore
376 431 $ for p in a b/a aa; do mkdir -p $p; touch $p/b.ext; done
377 432 $ hg status -A 'set:**.ext'
378 433 ? aa/b.ext
379 434 ? b/a/b.ext
380 435 I a/b.ext
381 436
382 437 Check using 'include:' in ignore file
383 438
384 439 $ hg purge --all --config extensions.purge=
385 440 $ touch foo.included
386 441
387 442 $ echo ".*.included" > otherignore
388 443 $ hg status -I "include:otherignore"
389 444 ? foo.included
390 445
391 446 $ echo "include:otherignore" >> .hgignore
392 447 $ hg status
393 448 A dir/b.o
394 449 ? .hgignore
395 450 ? otherignore
396 451
397 452 Check recursive uses of 'include:'
398 453
399 454 $ echo "include:nested/ignore" >> otherignore
400 455 $ mkdir nested nested/more
401 456 $ echo "glob:*ignore" > nested/ignore
402 457 $ echo "rootglob:a" >> nested/ignore
403 458 $ touch a nested/a nested/more/a
404 459 $ hg status
405 460 A dir/b.o
406 461 ? nested/a
407 462 ? nested/more/a
408 463 $ rm a nested/a nested/more/a
409 464
410 465 $ cp otherignore goodignore
411 466 $ echo "include:badignore" >> otherignore
412 467 $ hg status
413 468 skipping unreadable pattern file 'badignore': $ENOENT$
414 469 A dir/b.o
415 470
416 471 $ mv goodignore otherignore
417 472
418 473 Check using 'include:' while in a non-root directory
419 474
420 475 $ cd ..
421 476 $ hg -R ignorerepo status
422 477 A dir/b.o
423 478 $ cd ignorerepo
424 479
425 480 Check including subincludes
426 481
427 482 $ hg revert -q --all
428 483 $ hg purge --all --config extensions.purge=
429 484 $ echo ".hgignore" > .hgignore
430 485 $ mkdir dir1 dir2
431 486 $ touch dir1/file1 dir1/file2 dir2/file1 dir2/file2
432 487 $ echo "subinclude:dir2/.hgignore" >> .hgignore
433 488 $ echo "glob:file*2" > dir2/.hgignore
434 489 $ hg status
435 490 ? dir1/file1
436 491 ? dir1/file2
437 492 ? dir2/file1
438 493
439 494 Check including subincludes with other patterns
440 495
441 496 $ echo "subinclude:dir1/.hgignore" >> .hgignore
442 497
443 498 $ mkdir dir1/subdir
444 499 $ touch dir1/subdir/file1
445 500 $ echo "rootglob:f?le1" > dir1/.hgignore
446 501 $ hg status
447 502 ? dir1/file2
448 503 ? dir1/subdir/file1
449 504 ? dir2/file1
450 505 $ rm dir1/subdir/file1
451 506
452 507 $ echo "regexp:f.le1" > dir1/.hgignore
453 508 $ hg status
454 509 ? dir1/file2
455 510 ? dir2/file1
456 511
457 512 Check multiple levels of sub-ignores
458 513
459 514 $ touch dir1/subdir/subfile1 dir1/subdir/subfile3 dir1/subdir/subfile4
460 515 $ echo "subinclude:subdir/.hgignore" >> dir1/.hgignore
461 516 $ echo "glob:subfil*3" >> dir1/subdir/.hgignore
462 517
463 518 $ hg status
464 519 ? dir1/file2
465 520 ? dir1/subdir/subfile4
466 521 ? dir2/file1
467 522
468 523 Check include subignore at the same level
469 524
470 525 $ mv dir1/subdir/.hgignore dir1/.hgignoretwo
471 526 $ echo "regexp:f.le1" > dir1/.hgignore
472 527 $ echo "subinclude:.hgignoretwo" >> dir1/.hgignore
473 528 $ echo "glob:file*2" > dir1/.hgignoretwo
474 529
475 530 $ hg status | grep file2
476 531 [1]
477 532 $ hg debugignore dir1/file2
478 533 dir1/file2 is ignored
479 534 (ignore rule in dir2/.hgignore, line 1: 'file*2')
480 535
481 536 #if windows
482 537
483 538 Windows paths are accepted on input
484 539
485 540 $ rm dir1/.hgignore
486 541 $ echo "dir1/file*" >> .hgignore
487 542 $ hg debugignore "dir1\file2"
488 543 dir1/file2 is ignored
489 544 (ignore rule in $TESTTMP\ignorerepo\.hgignore, line 4: 'dir1/file*')
490 545 $ hg up -qC .
491 546
492 547 #endif
493 548
494 549 #if dirstate-v2 rust
495 550
496 551 Check the hash of ignore patterns written in the dirstate
497 552 This is an optimization that is only relevant when using the Rust extensions
498 553
499 554 $ cat_filename_and_hash () {
500 555 > for i in "$@"; do
501 556 > printf "$i "
502 557 > cat "$i" | "$TESTDIR"/f --raw-sha1 | sed 's/^raw-sha1=//'
503 558 > done
504 559 > }
505 560 $ hg status > /dev/null
506 561 $ cat_filename_and_hash .hg/testhgignore .hg/testhgignorerel .hgignore dir2/.hgignore dir1/.hgignore dir1/.hgignoretwo | $TESTDIR/f --sha1
507 562 sha1=c0beb296395d48ced8e14f39009c4ea6e409bfe6
508 563 $ hg debugstate --docket | grep ignore
509 564 ignore pattern hash: c0beb296395d48ced8e14f39009c4ea6e409bfe6
510 565
511 566 $ echo rel > .hg/testhgignorerel
512 567 $ hg status > /dev/null
513 568 $ cat_filename_and_hash .hg/testhgignore .hg/testhgignorerel .hgignore dir2/.hgignore dir1/.hgignore dir1/.hgignoretwo | $TESTDIR/f --sha1
514 569 sha1=b8e63d3428ec38abc68baa27631516d5ec46b7fa
515 570 $ hg debugstate --docket | grep ignore
516 571 ignore pattern hash: b8e63d3428ec38abc68baa27631516d5ec46b7fa
517 572 $ cd ..
518 573
519 574 Check that the hash depends on the source of the hgignore patterns
520 575 (otherwise the context is lost and things like subinclude are cached improperly)
521 576
522 577 $ hg init ignore-collision
523 578 $ cd ignore-collision
524 579 $ echo > .hg/testhgignorerel
525 580
526 581 $ mkdir dir1/ dir1/subdir
527 582 $ touch dir1/subdir/f dir1/subdir/ignored1
528 583 $ echo 'ignored1' > dir1/.hgignore
529 584
530 585 $ mkdir dir2 dir2/subdir
531 586 $ touch dir2/subdir/f dir2/subdir/ignored2
532 587 $ echo 'ignored2' > dir2/.hgignore
533 588 $ echo 'subinclude:dir2/.hgignore' >> .hgignore
534 589 $ echo 'subinclude:dir1/.hgignore' >> .hgignore
535 590
536 591 $ hg commit -Aqm_
537 592
538 593 $ > dir1/.hgignore
539 594 $ echo 'ignored' > dir2/.hgignore
540 595 $ echo 'ignored1' >> dir2/.hgignore
541 596 $ hg status
542 597 M dir1/.hgignore
543 598 M dir2/.hgignore
544 599 ? dir1/subdir/ignored1
545 600
546 601 #endif
General Comments 0
You need to be logged in to leave comments. Login now