##// END OF EJS Templates
api: expose new functions for FTS...
marcink -
r3460:866fba74 default
parent child
Show More
@@ -428,8 +428,8 def get_repo_nodes(request, apiuser, rep
428 ``all`` (default), ``files`` and ``dirs``.
428 ``all`` (default), ``files`` and ``dirs``.
429 :type ret_type: Optional(str)
429 :type ret_type: Optional(str)
430 :param details: Returns extended information about nodes, such as
430 :param details: Returns extended information about nodes, such as
431 md5, binary, and or content. The valid options are ``basic`` and
431 md5, binary, and or content.
432 ``full``.
432 The valid options are ``basic`` and ``full``.
433 :type details: Optional(str)
433 :type details: Optional(str)
434 :param max_file_bytes: Only return file content under this file size bytes
434 :param max_file_bytes: Only return file content under this file size bytes
435 :type details: Optional(int)
435 :type details: Optional(int)
@@ -440,12 +440,17 def get_repo_nodes(request, apiuser, rep
440
440
441 id : <id_given_in_input>
441 id : <id_given_in_input>
442 result: [
442 result: [
443 {
443 {
444 "name" : "<name>"
444 "binary": false,
445 "type" : "<type>",
445 "content": "File line\nLine2\n",
446 "binary": "<true|false>" (only in extended mode)
446 "extension": "md",
447 "md5" : "<md5 of file content>" (only in extended mode)
447 "lines": 2,
448 },
448 "md5": "059fa5d29b19c0657e384749480f6422",
449 "mimetype": "text/x-minidsrc",
450 "name": "file.md",
451 "size": 580,
452 "type": "file"
453 },
449 ...
454 ...
450 ]
455 ]
451 error: null
456 error: null
@@ -453,16 +458,14 def get_repo_nodes(request, apiuser, rep
453
458
454 repo = get_repo_or_error(repoid)
459 repo = get_repo_or_error(repoid)
455 if not has_superadmin_permission(apiuser):
460 if not has_superadmin_permission(apiuser):
456 _perms = (
461 _perms = ('repository.admin', 'repository.write', 'repository.read',)
457 'repository.admin', 'repository.write', 'repository.read',)
458 validate_repo_permissions(apiuser, repoid, repo, _perms)
462 validate_repo_permissions(apiuser, repoid, repo, _perms)
459
463
460 ret_type = Optional.extract(ret_type)
464 ret_type = Optional.extract(ret_type)
461 details = Optional.extract(details)
465 details = Optional.extract(details)
462 _extended_types = ['basic', 'full']
466 _extended_types = ['basic', 'full']
463 if details not in _extended_types:
467 if details not in _extended_types:
464 raise JSONRPCError(
468 raise JSONRPCError('ret_type must be one of %s' % (','.join(_extended_types)))
465 'ret_type must be one of %s' % (','.join(_extended_types)))
466 extended_info = False
469 extended_info = False
467 content = False
470 content = False
468 if details == 'basic':
471 if details == 'basic':
@@ -499,6 +502,117 def get_repo_nodes(request, apiuser, rep
499
502
500
503
501 @jsonrpc_method()
504 @jsonrpc_method()
505 def get_repo_file(request, apiuser, repoid, commit_id, file_path,
506 max_file_bytes=Optional(None), details=Optional('basic')):
507 """
508 Returns a single file from repository at given revision.
509
510 This command can only be run using an |authtoken| with admin rights,
511 or users with at least read rights to |repos|.
512
513 :param apiuser: This is filled automatically from the |authtoken|.
514 :type apiuser: AuthUser
515 :param repoid: The repository name or repository ID.
516 :type repoid: str or int
517 :param commit_id: The revision for which listing should be done.
518 :type commit_id: str
519 :param file_path: The path from which to start displaying.
520 :type file_path: str
521 :param details: Returns different set of information about nodes.
522 The valid options are ``minimal`` ``basic`` and ``full``.
523 :type details: Optional(str)
524 :param max_file_bytes: Only return file content under this file size bytes
525 :type details: Optional(int)
526
527 Example output:
528
529 .. code-block:: bash
530
531 id : <id_given_in_input>
532 result: {
533 "binary": false,
534 "extension": "py",
535 "lines": 35,
536 "content": "....",
537 "md5": "76318336366b0f17ee249e11b0c99c41",
538 "mimetype": "text/x-python",
539 "name": "python.py",
540 "size": 817,
541 "type": "file",
542 }
543 error: null
544 """
545
546 repo = get_repo_or_error(repoid)
547 if not has_superadmin_permission(apiuser):
548 _perms = ('repository.admin', 'repository.write', 'repository.read',)
549 validate_repo_permissions(apiuser, repoid, repo, _perms)
550
551 details = Optional.extract(details)
552 _extended_types = ['minimal', 'minimal+search', 'basic', 'full']
553 if details not in _extended_types:
554 raise JSONRPCError(
555 'ret_type must be one of %s, got %s' % (','.join(_extended_types)), details)
556 extended_info = False
557 content = False
558
559 if details == 'minimal':
560 extended_info = False
561
562 elif details == 'basic':
563 extended_info = True
564
565 elif details == 'full':
566 extended_info = content = True
567
568 try:
569 # check if repo is not empty by any chance, skip quicker if it is.
570 _scm = repo.scm_instance()
571 if _scm.is_empty():
572 return None
573
574 node = ScmModel().get_node(
575 repo, commit_id, file_path, extended_info=extended_info,
576 content=content, max_file_bytes=max_file_bytes)
577
578 except Exception:
579 log.exception("Exception occurred while trying to get repo node")
580 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
581
582 return node
583
584
585 @jsonrpc_method()
586 def get_repo_fts_tree(request, apiuser, repoid, commit_id, root_path):
587 """
588 Returns a list of tree nodes for path at given revision. This api is built
589 strictly for usage in full text search building, and shouldn't be consumed
590
591 This command can only be run using an |authtoken| with admin rights,
592 or users with at least read rights to |repos|.
593
594 """
595
596 repo = get_repo_or_error(repoid)
597 if not has_superadmin_permission(apiuser):
598 _perms = ('repository.admin', 'repository.write', 'repository.read',)
599 validate_repo_permissions(apiuser, repoid, repo, _perms)
600
601 try:
602 # check if repo is not empty by any chance, skip quicker if it is.
603 _scm = repo.scm_instance()
604 if _scm.is_empty():
605 return []
606
607 tree_files = ScmModel().get_fts_data(repo, commit_id, root_path)
608 return tree_files
609
610 except Exception:
611 log.exception("Exception occurred while trying to get repo nodes")
612 raise JSONRPCError('failed to get repo: `%s` nodes' % repo.repo_name)
613
614
615 @jsonrpc_method()
502 def get_repo_refs(request, apiuser, repoid):
616 def get_repo_refs(request, apiuser, repoid):
503 """
617 """
504 Returns a dictionary of current references. It returns
618 Returns a dictionary of current references. It returns
@@ -372,6 +372,22 class FileNode(Node):
372 """
372 """
373 return md5(self.raw_bytes)
373 return md5(self.raw_bytes)
374
374
375 def metadata_uncached(self):
376 """
377 Returns md5, binary flag of the file node, without any cache usage.
378 """
379
380 if self.commit:
381 content = self.commit.get_file_content(self.path)
382 else:
383 content = self._content
384
385 is_binary = content and '\0' in content
386 size = 0
387 if content:
388 size = len(content)
389 return is_binary, md5(content), size
390
375 @LazyProperty
391 @LazyProperty
376 def content(self):
392 def content(self):
377 """
393 """
@@ -573,11 +573,93 class ScmModel(BaseModel):
573 })
573 })
574 _dirs.append(_data)
574 _dirs.append(_data)
575 except RepositoryError:
575 except RepositoryError:
576 log.debug("Exception in get_nodes", exc_info=True)
576 log.exception("Exception in get_nodes")
577 raise
577 raise
578
578
579 return _dirs, _files
579 return _dirs, _files
580
580
581 def get_node(self, repo_name, commit_id, file_path,
582 extended_info=False, content=False, max_file_bytes=None):
583 """
584 retrieve single node from commit
585 """
586 try:
587
588 _repo = self._get_repo(repo_name)
589 commit = _repo.scm_instance().get_commit(commit_id=commit_id)
590
591 file_node = commit.get_node(file_path)
592 if file_node.is_dir():
593 raise RepositoryError('The given path is a directory')
594
595 _content = None
596 f_name = file_node.unicode_path
597
598 file_data = {
599 "name": h.escape(f_name),
600 "type": "file",
601 }
602
603 if extended_info:
604 file_data.update({
605 "md5": file_node.md5,
606 "binary": file_node.is_binary,
607 "size": file_node.size,
608 "extension": file_node.extension,
609 "mimetype": file_node.mimetype,
610 "lines": file_node.lines()[0]
611 })
612
613 if content:
614 over_size_limit = (max_file_bytes is not None
615 and file_node.size > max_file_bytes)
616 full_content = None
617 if not file_node.is_binary and not over_size_limit:
618 full_content = safe_str(file_node.content)
619
620 file_data.update({
621 "content": full_content,
622 })
623
624 except RepositoryError:
625 log.exception("Exception in get_node")
626 raise
627
628 return file_data
629
630 def get_fts_data(self, repo_name, commit_id, root_path='/'):
631 """
632 Fetch node tree for usage in full text search
633 """
634
635 tree_info = list()
636
637 try:
638 _repo = self._get_repo(repo_name)
639 commit = _repo.scm_instance().get_commit(commit_id=commit_id)
640 root_path = root_path.lstrip('/')
641 for __, dirs, files in commit.walk(root_path):
642
643 for f in files:
644 _content = None
645 _data = f_name = f.unicode_path
646 is_binary, md5, size = f.metadata_uncached()
647 _data = {
648 "name": h.escape(f_name),
649 "md5": md5,
650 "extension": f.extension,
651 "binary": is_binary,
652 "size": size
653 }
654
655 tree_info.append(_data)
656
657 except RepositoryError:
658 log.exception("Exception in get_nodes")
659 raise
660
661 return tree_info
662
581 def create_nodes(self, user, repo, message, nodes, parent_commit=None,
663 def create_nodes(self, user, repo, message, nodes, parent_commit=None,
582 author=None, trigger_push_hook=True):
664 author=None, trigger_push_hook=True):
583 """
665 """
General Comments 0
You need to be logged in to leave comments. Login now