def ComputeSortDirectives(config, group_by_spec, sort_spec, tie_breakers=None):
  """Return a list with sort directives to be used in sorting.

  Args:
    config: Project config PB instance that defines the sort order for
        labels and statuses in this project.
    group_by_spec: string that lists the grouping order
    sort_spec: string that lists the sort order
    tie_breakers: list of column names to add to the end of the sort
        spec if they are not already somewhere in the sort spec.

  Returns:
    A list of lower-case column names, each one may have a leading
    minus-sign.
  """
  # Prepend the end-user's sort spec to any project default sort spec.
  if tie_breakers is None:
    tie_breakers = ['id']
  sort_spec = '%s %s %s' % (
      group_by_spec, sort_spec, config.default_sort_spec)
  # Sort specs can have interfering sort orders, so remove any duplicates.
  field_names = set()
  sort_directives = []
  for sort_directive in sort_spec.lower().split():
    field_name = sort_directive.lstrip('-')
    if field_name not in field_names:
      sort_directives.append(sort_directive)
      field_names.add(field_name)

  # Add in the project name so that the overall ordering is completely
  # defined in cross-project search. Otherwise, issues jump up and
  # down on each reload of the same query, and prev/next links get
  # messed up.  It's a no-op in single projects.
  if 'project' not in sort_directives:
    sort_directives.append('project')

  for tie_breaker in tie_breakers:
    if tie_breaker not in sort_directives:
      sort_directives.append(tie_breaker)

  return sort_directives